blob: c3304164cab9f51d4bac0c5c0b014a6544f1a595 [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))
844 return 0x01;
845
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
886static void update_scan_rsp_data_for_instance(struct hci_request *req,
887 u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700888{
889 struct hci_dev *hdev = req->hdev;
890 struct hci_cp_le_set_scan_rsp_data cp;
891 u8 len;
892
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700893 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700894 return;
895
896 memset(&cp, 0, sizeof(cp));
897
Arman Uguray4117ed72015-03-23 15:57:14 -0700898 if (instance)
899 len = create_instance_scan_rsp_data(hdev, cp.data);
900 else
901 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700902
Johan Hedbergeb438b52013-10-16 15:31:07 +0300903 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700904 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700905 return;
906
Johan Hedbergeb438b52013-10-16 15:31:07 +0300907 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
908 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700909
910 cp.length = len;
911
912 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
913}
914
Arman Uguray4117ed72015-03-23 15:57:14 -0700915static void update_scan_rsp_data(struct hci_request *req)
916{
Florian Grandel91aa9bb2015-06-18 03:16:36 +0200917 update_scan_rsp_data_for_instance(req,
918 get_current_adv_instance(req->hdev));
Arman Uguray4117ed72015-03-23 15:57:14 -0700919}
920
Johan Hedberg9a43e252013-10-20 19:00:07 +0300921static u8 get_adv_discov_flags(struct hci_dev *hdev)
922{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200923 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300924
925 /* If there's a pending mgmt command the flags will not yet have
926 * their final values, so check for this first.
927 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200928 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300929 if (cmd) {
930 struct mgmt_mode *cp = cmd->param;
931 if (cp->val == 0x01)
932 return LE_AD_GENERAL;
933 else if (cp->val == 0x02)
934 return LE_AD_LIMITED;
935 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700936 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300937 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700938 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300939 return LE_AD_GENERAL;
940 }
941
942 return 0;
943}
944
Arman Uguraye7a685d2015-03-25 18:53:40 -0700945static bool get_connectable(struct hci_dev *hdev)
946{
947 struct mgmt_pending_cmd *cmd;
948
949 /* If there's a pending mgmt command the flag will not yet have
950 * it's final value, so check for this first.
951 */
952 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
953 if (cmd) {
954 struct mgmt_mode *cp = cmd->param;
955
956 return cp->val;
957 }
958
959 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
960}
961
962static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
963{
964 u32 flags;
965
966 if (instance > 0x01)
967 return 0;
968
Arman Ugurayfdf51782015-03-25 18:53:46 -0700969 if (instance == 0x01)
Arman Uguraye7a685d2015-03-25 18:53:40 -0700970 return hdev->adv_instance.flags;
971
Arman Ugurayfdf51782015-03-25 18:53:46 -0700972 /* Instance 0 always manages the "Tx Power" and "Flags" fields */
973 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700974
Arman Ugurayfaccb952015-03-28 12:38:58 -0700975 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting corresponds
976 * to the "connectable" instance flag.
977 */
978 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700979 flags |= MGMT_ADV_FLAG_CONNECTABLE;
980
Arman Uguraye7a685d2015-03-25 18:53:40 -0700981 return flags;
982}
983
Arman Ugurayc7d48832015-03-28 12:38:59 -0700984static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
985{
986 /* Ignore instance 0 and other unsupported instances */
987 if (instance != 0x01)
988 return 0;
989
990 /* TODO: Take into account the "appearance" and "local-name" flags here.
991 * These are currently being ignored as they are not supported.
992 */
993 return hdev->adv_instance.scan_rsp_len;
994}
995
Arman Ugurayfdf51782015-03-25 18:53:46 -0700996static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
997{
998 u8 ad_len = 0, flags = 0;
999 u32 instance_flags = get_adv_instance_flags(hdev, instance);
1000
1001 /* The Add Advertising command allows userspace to set both the general
1002 * and limited discoverable flags.
1003 */
1004 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1005 flags |= LE_AD_GENERAL;
1006
1007 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1008 flags |= LE_AD_LIMITED;
1009
1010 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1011 /* If a discovery flag wasn't provided, simply use the global
1012 * settings.
1013 */
1014 if (!flags)
1015 flags |= get_adv_discov_flags(hdev);
1016
1017 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1018 flags |= LE_AD_NO_BREDR;
1019
1020 /* If flags would still be empty, then there is no need to
1021 * include the "Flags" AD field".
1022 */
1023 if (flags) {
1024 ptr[0] = 0x02;
1025 ptr[1] = EIR_FLAGS;
1026 ptr[2] = flags;
1027
1028 ad_len += 3;
1029 ptr += 3;
1030 }
1031 }
1032
Marcel Holtmann38c8af62015-04-03 13:23:12 -07001033 if (instance) {
1034 memcpy(ptr, hdev->adv_instance.adv_data,
1035 hdev->adv_instance.adv_data_len);
1036
1037 ad_len += hdev->adv_instance.adv_data_len;
1038 ptr += hdev->adv_instance.adv_data_len;
1039 }
1040
Arman Ugurayfdf51782015-03-25 18:53:46 -07001041 /* Provide Tx Power only if we can provide a valid value for it */
1042 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1043 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1044 ptr[0] = 0x02;
1045 ptr[1] = EIR_TX_POWER;
1046 ptr[2] = (u8)hdev->adv_tx_power;
1047
1048 ad_len += 3;
1049 ptr += 3;
1050 }
1051
Arman Ugurayfdf51782015-03-25 18:53:46 -07001052 return ad_len;
1053}
1054
1055static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
1056{
1057 struct hci_dev *hdev = req->hdev;
1058 struct hci_cp_le_set_adv_data cp;
1059 u8 len;
1060
1061 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1062 return;
1063
1064 memset(&cp, 0, sizeof(cp));
1065
1066 len = create_instance_adv_data(hdev, instance, cp.data);
1067
1068 /* There's nothing to do if the data hasn't changed */
1069 if (hdev->adv_data_len == len &&
1070 memcmp(cp.data, hdev->adv_data, len) == 0)
1071 return;
1072
1073 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1074 hdev->adv_data_len = len;
1075
1076 cp.length = len;
1077
1078 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1079}
1080
Arman Uguraye7a685d2015-03-25 18:53:40 -07001081static void update_adv_data(struct hci_request *req)
1082{
Florian Grandel91aa9bb2015-06-18 03:16:36 +02001083 update_adv_data_for_instance(req, get_current_adv_instance(req->hdev));
Arman Uguray24b4f382015-03-23 15:57:12 -07001084}
1085
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001086int mgmt_update_adv_data(struct hci_dev *hdev)
1087{
1088 struct hci_request req;
1089
1090 hci_req_init(&req, hdev);
1091 update_adv_data(&req);
1092
1093 return hci_req_run(&req, NULL);
1094}
1095
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001096static void create_eir(struct hci_dev *hdev, u8 *data)
1097{
1098 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001099 size_t name_len;
1100
1101 name_len = strlen(hdev->dev_name);
1102
1103 if (name_len > 0) {
1104 /* EIR Data type */
1105 if (name_len > 48) {
1106 name_len = 48;
1107 ptr[1] = EIR_NAME_SHORT;
1108 } else
1109 ptr[1] = EIR_NAME_COMPLETE;
1110
1111 /* EIR Data length */
1112 ptr[0] = name_len + 1;
1113
1114 memcpy(ptr + 2, hdev->dev_name, name_len);
1115
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001116 ptr += (name_len + 2);
1117 }
1118
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001119 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001120 ptr[0] = 2;
1121 ptr[1] = EIR_TX_POWER;
1122 ptr[2] = (u8) hdev->inq_tx_power;
1123
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001124 ptr += 3;
1125 }
1126
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001127 if (hdev->devid_source > 0) {
1128 ptr[0] = 9;
1129 ptr[1] = EIR_DEVICE_ID;
1130
1131 put_unaligned_le16(hdev->devid_source, ptr + 2);
1132 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1133 put_unaligned_le16(hdev->devid_product, ptr + 6);
1134 put_unaligned_le16(hdev->devid_version, ptr + 8);
1135
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001136 ptr += 10;
1137 }
1138
Johan Hedberg213202e2013-01-27 00:31:33 +02001139 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001140 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001141 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001142}
1143
Johan Hedberg890ea892013-03-15 17:06:52 -05001144static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001145{
Johan Hedberg890ea892013-03-15 17:06:52 -05001146 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001147 struct hci_cp_write_eir cp;
1148
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001149 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001150 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001151
Johan Hedberg976eb202012-10-24 21:12:01 +03001152 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001153 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001154
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001155 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
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_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001159 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001160
1161 memset(&cp, 0, sizeof(cp));
1162
1163 create_eir(hdev, cp.data);
1164
1165 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001166 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001167
1168 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1169
Johan Hedberg890ea892013-03-15 17:06:52 -05001170 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001171}
1172
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001173static u8 get_service_classes(struct hci_dev *hdev)
1174{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001175 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001176 u8 val = 0;
1177
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001178 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001179 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001180
1181 return val;
1182}
1183
Johan Hedberg890ea892013-03-15 17:06:52 -05001184static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001185{
Johan Hedberg890ea892013-03-15 17:06:52 -05001186 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001187 u8 cod[3];
1188
1189 BT_DBG("%s", hdev->name);
1190
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001191 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001192 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001193
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001194 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001195 return;
1196
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001197 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001198 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001199
1200 cod[0] = hdev->minor_class;
1201 cod[1] = hdev->major_class;
1202 cod[2] = get_service_classes(hdev);
1203
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001204 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001205 cod[1] |= 0x20;
1206
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001207 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001208 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001209
Johan Hedberg890ea892013-03-15 17:06:52 -05001210 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001211}
1212
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001213static void disable_advertising(struct hci_request *req)
1214{
1215 u8 enable = 0x00;
1216
1217 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1218}
1219
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001220static void enable_advertising(struct hci_request *req)
1221{
1222 struct hci_dev *hdev = req->hdev;
1223 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001224 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001225 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001226 u8 instance;
1227 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001228
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001229 if (hci_conn_num(hdev, LE_LINK) > 0)
1230 return;
1231
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001232 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001233 disable_advertising(req);
1234
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001235 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001236 * hci_update_random_address knows that it's safe to go ahead
1237 * and write a new random address. The flag will be set back on
1238 * as soon as the SET_ADV_ENABLE HCI command completes.
1239 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001240 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001241
Arman Uguraye7a685d2015-03-25 18:53:40 -07001242 instance = get_current_adv_instance(hdev);
1243 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001244
1245 /* If the "connectable" instance flag was not set, then choose between
1246 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1247 */
1248 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1249 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001250
Johan Hedberga4858cb2014-02-25 19:56:31 +02001251 /* Set require_privacy to true only when non-connectable
1252 * advertising is used. In that case it is fine to use a
1253 * non-resolvable private address.
1254 */
1255 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001256 return;
1257
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001258 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001259 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1260 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001261
1262 if (connectable)
1263 cp.type = LE_ADV_IND;
1264 else if (get_adv_instance_scan_rsp_len(hdev, instance))
1265 cp.type = LE_ADV_SCAN_IND;
1266 else
1267 cp.type = LE_ADV_NONCONN_IND;
1268
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001269 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001270 cp.channel_map = hdev->le_adv_channel_map;
1271
1272 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1273
1274 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1275}
1276
Johan Hedberg7d785252011-12-15 00:47:39 +02001277static void service_cache_off(struct work_struct *work)
1278{
1279 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001280 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001281 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001282
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001283 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001284 return;
1285
Johan Hedberg890ea892013-03-15 17:06:52 -05001286 hci_req_init(&req, hdev);
1287
Johan Hedberg7d785252011-12-15 00:47:39 +02001288 hci_dev_lock(hdev);
1289
Johan Hedberg890ea892013-03-15 17:06:52 -05001290 update_eir(&req);
1291 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001292
1293 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001294
1295 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001296}
1297
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001298static void rpa_expired(struct work_struct *work)
1299{
1300 struct hci_dev *hdev = container_of(work, struct hci_dev,
1301 rpa_expired.work);
1302 struct hci_request req;
1303
1304 BT_DBG("");
1305
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001306 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001307
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001308 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001309 return;
1310
1311 /* The generation of a new RPA and programming it into the
1312 * controller happens in the enable_advertising() function.
1313 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001314 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001315 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001316 hci_req_run(&req, NULL);
1317}
1318
Johan Hedberg6a919082012-02-28 06:17:26 +02001319static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001320{
Marcel Holtmann238be782015-03-13 02:11:06 -07001321 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001322 return;
1323
Johan Hedberg4f87da82012-03-02 19:55:56 +02001324 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001325 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001326
Johan Hedberg4f87da82012-03-02 19:55:56 +02001327 /* Non-mgmt controlled devices get this bit set
1328 * implicitly so that pairing works for them, however
1329 * for mgmt we require user-space to explicitly enable
1330 * it
1331 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001332 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001333}
1334
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001335static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001336 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001337{
1338 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001339
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001340 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001341
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001342 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001343
Johan Hedberg03811012010-12-08 00:21:06 +02001344 memset(&rp, 0, sizeof(rp));
1345
Johan Hedberg03811012010-12-08 00:21:06 +02001346 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001347
1348 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001349 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001350
1351 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1352 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1353
1354 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001355
1356 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001357 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001358
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001359 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001360
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001361 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1362 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001363}
1364
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001365static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001366{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001367 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001368
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001369 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1370 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001371}
1372
Marcel Holtmann1904a852015-01-11 13:50:44 -08001373static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001374{
1375 BT_DBG("%s status 0x%02x", hdev->name, status);
1376
Johan Hedberga3172b72014-02-28 09:33:44 +02001377 if (hci_conn_count(hdev) == 0) {
1378 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001379 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001380 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001381}
1382
Johan Hedberg23a48092014-07-08 16:05:06 +03001383static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001384{
1385 struct hci_dev *hdev = req->hdev;
1386 struct hci_cp_remote_name_req_cancel cp;
1387 struct inquiry_entry *e;
1388
1389 switch (hdev->discovery.state) {
1390 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001391 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001392 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001393
1394 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001395 cancel_delayed_work(&hdev->le_scan_disable);
1396 hci_req_add_le_scan_disable(req);
1397 }
1398
Johan Hedberg23a48092014-07-08 16:05:06 +03001399 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001400
1401 case DISCOVERY_RESOLVING:
1402 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1403 NAME_PENDING);
1404 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001405 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001406
1407 bacpy(&cp.bdaddr, &e->data.bdaddr);
1408 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1409 &cp);
1410
Johan Hedberg23a48092014-07-08 16:05:06 +03001411 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001412
1413 default:
1414 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001415 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001416 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001417 return true;
1418 }
1419
Johan Hedberg21a60d32014-06-10 14:05:58 +03001420 break;
1421 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001422
1423 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001424}
1425
Arman Uguray912098a2015-03-23 15:57:15 -07001426static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1427 u8 instance)
1428{
1429 struct mgmt_ev_advertising_added ev;
1430
1431 ev.instance = instance;
1432
1433 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1434}
1435
1436static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1437 u8 instance)
1438{
1439 struct mgmt_ev_advertising_removed ev;
1440
1441 ev.instance = instance;
1442
1443 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1444}
1445
1446static void clear_adv_instance(struct hci_dev *hdev)
1447{
1448 struct hci_request req;
1449
1450 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1451 return;
1452
Florian Grandel5d900e42015-06-18 03:16:35 +02001453 if (hdev->adv_instance_timeout)
1454 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07001455
1456 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1457 advertising_removed(NULL, hdev, 1);
1458 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1459
1460 if (!hdev_is_powered(hdev) ||
1461 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1462 return;
1463
1464 hci_req_init(&req, hdev);
1465 disable_advertising(&req);
1466 hci_req_run(&req, NULL);
1467}
1468
Johan Hedberg8b064a32014-02-24 14:52:22 +02001469static int clean_up_hci_state(struct hci_dev *hdev)
1470{
1471 struct hci_request req;
1472 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001473 bool discov_stopped;
1474 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001475
1476 hci_req_init(&req, hdev);
1477
1478 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1479 test_bit(HCI_PSCAN, &hdev->flags)) {
1480 u8 scan = 0x00;
1481 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1482 }
1483
Florian Grandel5d900e42015-06-18 03:16:35 +02001484 if (hdev->adv_instance_timeout)
Arman Uguray912098a2015-03-23 15:57:15 -07001485 clear_adv_instance(hdev);
1486
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001487 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001488 disable_advertising(&req);
1489
Johan Hedberg23a48092014-07-08 16:05:06 +03001490 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001491
1492 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1493 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001494 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001495
Johan Hedbergc9910d02014-02-27 14:35:12 +02001496 switch (conn->state) {
1497 case BT_CONNECTED:
1498 case BT_CONFIG:
1499 dc.handle = cpu_to_le16(conn->handle);
1500 dc.reason = 0x15; /* Terminated due to Power Off */
1501 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1502 break;
1503 case BT_CONNECT:
1504 if (conn->type == LE_LINK)
1505 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1506 0, NULL);
1507 else if (conn->type == ACL_LINK)
1508 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1509 6, &conn->dst);
1510 break;
1511 case BT_CONNECT2:
1512 bacpy(&rej.bdaddr, &conn->dst);
1513 rej.reason = 0x15; /* Terminated due to Power Off */
1514 if (conn->type == ACL_LINK)
1515 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1516 sizeof(rej), &rej);
1517 else if (conn->type == SCO_LINK)
1518 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1519 sizeof(rej), &rej);
1520 break;
1521 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001522 }
1523
Johan Hedberg23a48092014-07-08 16:05:06 +03001524 err = hci_req_run(&req, clean_up_hci_complete);
1525 if (!err && discov_stopped)
1526 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1527
1528 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001529}
1530
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001531static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001532 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001533{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001534 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001535 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001536 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001537
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001538 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001539
Johan Hedberga7e80f22013-01-09 16:05:19 +02001540 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001541 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1542 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001543
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001544 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001545
Johan Hedberg333ae952015-03-17 13:48:47 +02001546 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001547 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1548 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001549 goto failed;
1550 }
1551
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001552 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001553 cancel_delayed_work(&hdev->power_off);
1554
1555 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001556 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1557 data, len);
1558 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001559 goto failed;
1560 }
1561 }
1562
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001563 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001564 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001565 goto failed;
1566 }
1567
Johan Hedberg03811012010-12-08 00:21:06 +02001568 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1569 if (!cmd) {
1570 err = -ENOMEM;
1571 goto failed;
1572 }
1573
Johan Hedberg8b064a32014-02-24 14:52:22 +02001574 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001575 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001576 err = 0;
1577 } else {
1578 /* Disconnect connections, stop scans, etc */
1579 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001580 if (!err)
1581 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1582 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001583
Johan Hedberg8b064a32014-02-24 14:52:22 +02001584 /* ENODATA means there were no HCI commands queued */
1585 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001586 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001587 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1588 err = 0;
1589 }
1590 }
Johan Hedberg03811012010-12-08 00:21:06 +02001591
1592failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001593 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001594 return err;
1595}
1596
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001597static int new_settings(struct hci_dev *hdev, struct sock *skip)
1598{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001599 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001600
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001601 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1602 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001603}
1604
Johan Hedberg91a668b2014-07-09 13:28:26 +03001605int mgmt_new_settings(struct hci_dev *hdev)
1606{
1607 return new_settings(hdev, NULL);
1608}
1609
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001610struct cmd_lookup {
1611 struct sock *sk;
1612 struct hci_dev *hdev;
1613 u8 mgmt_status;
1614};
1615
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001616static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001617{
1618 struct cmd_lookup *match = data;
1619
1620 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1621
1622 list_del(&cmd->list);
1623
1624 if (match->sk == NULL) {
1625 match->sk = cmd->sk;
1626 sock_hold(match->sk);
1627 }
1628
1629 mgmt_pending_free(cmd);
1630}
1631
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001632static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001633{
1634 u8 *status = data;
1635
Johan Hedberga69e8372015-03-06 21:08:53 +02001636 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001637 mgmt_pending_remove(cmd);
1638}
1639
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001640static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001641{
1642 if (cmd->cmd_complete) {
1643 u8 *status = data;
1644
1645 cmd->cmd_complete(cmd, *status);
1646 mgmt_pending_remove(cmd);
1647
1648 return;
1649 }
1650
1651 cmd_status_rsp(cmd, data);
1652}
1653
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001654static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001655{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001656 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1657 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001658}
1659
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001660static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001661{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001662 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1663 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001664}
1665
Johan Hedberge6fe7982013-10-02 15:45:22 +03001666static u8 mgmt_bredr_support(struct hci_dev *hdev)
1667{
1668 if (!lmp_bredr_capable(hdev))
1669 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001670 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001671 return MGMT_STATUS_REJECTED;
1672 else
1673 return MGMT_STATUS_SUCCESS;
1674}
1675
1676static u8 mgmt_le_support(struct hci_dev *hdev)
1677{
1678 if (!lmp_le_capable(hdev))
1679 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001680 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001681 return MGMT_STATUS_REJECTED;
1682 else
1683 return MGMT_STATUS_SUCCESS;
1684}
1685
Marcel Holtmann1904a852015-01-11 13:50:44 -08001686static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1687 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001688{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001689 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001690 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001691 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001692 bool changed;
1693
1694 BT_DBG("status 0x%02x", status);
1695
1696 hci_dev_lock(hdev);
1697
Johan Hedberg333ae952015-03-17 13:48:47 +02001698 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001699 if (!cmd)
1700 goto unlock;
1701
1702 if (status) {
1703 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001704 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001705 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001706 goto remove_cmd;
1707 }
1708
1709 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001710 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001711 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001712
1713 if (hdev->discov_timeout > 0) {
1714 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1715 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1716 to);
1717 }
1718 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001719 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001720 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001721
1722 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1723
1724 if (changed)
1725 new_settings(hdev, cmd->sk);
1726
Marcel Holtmann970ba522013-10-15 06:33:57 -07001727 /* When the discoverable mode gets changed, make sure
1728 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001729 * bit correctly set. Also update page scan based on whitelist
1730 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001731 */
1732 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001733 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001734 update_class(&req);
1735 hci_req_run(&req, NULL);
1736
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737remove_cmd:
1738 mgmt_pending_remove(cmd);
1739
1740unlock:
1741 hci_dev_unlock(hdev);
1742}
1743
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001744static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001745 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001746{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001747 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001748 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001749 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001750 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001751 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001752 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001753
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001754 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001755
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001756 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1757 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001758 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1759 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001760
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001761 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001762 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1763 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001764
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001765 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001766
1767 /* Disabling discoverable requires that no timeout is set,
1768 * and enabling limited discoverable requires a timeout.
1769 */
1770 if ((cp->val == 0x00 && timeout > 0) ||
1771 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001772 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1773 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001774
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001775 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001776
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001777 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001778 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1779 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001780 goto failed;
1781 }
1782
Johan Hedberg333ae952015-03-17 13:48:47 +02001783 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1784 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001785 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1786 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001787 goto failed;
1788 }
1789
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001790 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001791 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1792 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001793 goto failed;
1794 }
1795
1796 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001797 bool changed = false;
1798
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001799 /* Setting limited discoverable when powered off is
1800 * not a valid operation since it requires a timeout
1801 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1802 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001803 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001804 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001805 changed = true;
1806 }
1807
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001808 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001809 if (err < 0)
1810 goto failed;
1811
1812 if (changed)
1813 err = new_settings(hdev, sk);
1814
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001815 goto failed;
1816 }
1817
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001818 /* If the current mode is the same, then just update the timeout
1819 * value with the new value. And if only the timeout gets updated,
1820 * then no need for any HCI transactions.
1821 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001822 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1823 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1824 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001825 cancel_delayed_work(&hdev->discov_off);
1826 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001827
Marcel Holtmann36261542013-10-15 08:28:51 -07001828 if (cp->val && hdev->discov_timeout > 0) {
1829 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001830 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001831 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001832 }
1833
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001834 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001835 goto failed;
1836 }
1837
1838 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1839 if (!cmd) {
1840 err = -ENOMEM;
1841 goto failed;
1842 }
1843
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001844 /* Cancel any potential discoverable timeout that might be
1845 * still active and store new timeout value. The arming of
1846 * the timeout happens in the complete handler.
1847 */
1848 cancel_delayed_work(&hdev->discov_off);
1849 hdev->discov_timeout = timeout;
1850
Johan Hedbergb456f872013-10-19 23:38:22 +03001851 /* Limited discoverable mode */
1852 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001853 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001854 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001855 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001856
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001857 hci_req_init(&req, hdev);
1858
Johan Hedberg9a43e252013-10-20 19:00:07 +03001859 /* The procedure for LE-only controllers is much simpler - just
1860 * update the advertising data.
1861 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001862 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001863 goto update_ad;
1864
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001865 scan = SCAN_PAGE;
1866
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001867 if (cp->val) {
1868 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001869
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001870 if (cp->val == 0x02) {
1871 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001872 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001873 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1874 hci_cp.iac_lap[1] = 0x8b;
1875 hci_cp.iac_lap[2] = 0x9e;
1876 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1877 hci_cp.iac_lap[4] = 0x8b;
1878 hci_cp.iac_lap[5] = 0x9e;
1879 } else {
1880 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001881 hci_cp.num_iac = 1;
1882 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1883 hci_cp.iac_lap[1] = 0x8b;
1884 hci_cp.iac_lap[2] = 0x9e;
1885 }
1886
1887 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1888 (hci_cp.num_iac * 3) + 1, &hci_cp);
1889
1890 scan |= SCAN_INQUIRY;
1891 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001892 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001893 }
1894
1895 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001896
Johan Hedberg9a43e252013-10-20 19:00:07 +03001897update_ad:
1898 update_adv_data(&req);
1899
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001900 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001901 if (err < 0)
1902 mgmt_pending_remove(cmd);
1903
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001904failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001905 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001906 return err;
1907}
1908
Johan Hedberg406d7802013-03-15 17:07:09 -05001909static void write_fast_connectable(struct hci_request *req, bool enable)
1910{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001911 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001912 struct hci_cp_write_page_scan_activity acp;
1913 u8 type;
1914
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001915 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001916 return;
1917
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001918 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1919 return;
1920
Johan Hedberg406d7802013-03-15 17:07:09 -05001921 if (enable) {
1922 type = PAGE_SCAN_TYPE_INTERLACED;
1923
1924 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001925 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001926 } else {
1927 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1928
1929 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001930 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001931 }
1932
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001933 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001934
Johan Hedbergbd98b992013-03-15 17:07:13 -05001935 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1936 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1937 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1938 sizeof(acp), &acp);
1939
1940 if (hdev->page_scan_type != type)
1941 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001942}
1943
Marcel Holtmann1904a852015-01-11 13:50:44 -08001944static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1945 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001946{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001947 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001948 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001949 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001950
1951 BT_DBG("status 0x%02x", status);
1952
1953 hci_dev_lock(hdev);
1954
Johan Hedberg333ae952015-03-17 13:48:47 +02001955 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001956 if (!cmd)
1957 goto unlock;
1958
Johan Hedberg37438c12013-10-14 16:20:05 +03001959 if (status) {
1960 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001961 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001962 goto remove_cmd;
1963 }
1964
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001965 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001966 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001967 conn_changed = !hci_dev_test_and_set_flag(hdev,
1968 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001969 discov_changed = false;
1970 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001971 conn_changed = hci_dev_test_and_clear_flag(hdev,
1972 HCI_CONNECTABLE);
1973 discov_changed = hci_dev_test_and_clear_flag(hdev,
1974 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001975 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001976
Johan Hedberg2b76f452013-03-15 17:07:04 -05001977 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1978
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001979 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001980 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001981 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001982 if (discov_changed)
1983 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001984 hci_update_background_scan(hdev);
1985 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001986
Johan Hedberg37438c12013-10-14 16:20:05 +03001987remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001988 mgmt_pending_remove(cmd);
1989
1990unlock:
1991 hci_dev_unlock(hdev);
1992}
1993
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001994static int set_connectable_update_settings(struct hci_dev *hdev,
1995 struct sock *sk, u8 val)
1996{
1997 bool changed = false;
1998 int err;
1999
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002000 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002001 changed = true;
2002
2003 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002004 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002005 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002006 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2007 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002008 }
2009
2010 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2011 if (err < 0)
2012 return err;
2013
Johan Hedberg562064e2014-07-08 16:35:34 +03002014 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002015 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002016 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002017 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002018 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002019
2020 return 0;
2021}
2022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002023static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002024 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002025{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002026 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002027 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002028 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002029 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002030 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002031
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002032 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002033
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002034 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2035 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002036 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2037 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002038
Johan Hedberga7e80f22013-01-09 16:05:19 +02002039 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002040 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2041 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002042
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002043 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002044
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002045 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002046 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002047 goto failed;
2048 }
2049
Johan Hedberg333ae952015-03-17 13:48:47 +02002050 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2051 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002052 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2053 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002054 goto failed;
2055 }
2056
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002057 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2058 if (!cmd) {
2059 err = -ENOMEM;
2060 goto failed;
2061 }
2062
Johan Hedberg2b76f452013-03-15 17:07:04 -05002063 hci_req_init(&req, hdev);
2064
Johan Hedberg9a43e252013-10-20 19:00:07 +03002065 /* If BR/EDR is not enabled and we disable advertising as a
2066 * by-product of disabling connectable, we need to update the
2067 * advertising flags.
2068 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002069 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002070 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002071 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2072 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002073 }
2074 update_adv_data(&req);
2075 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002076 if (cp->val) {
2077 scan = SCAN_PAGE;
2078 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002079 /* If we don't have any whitelist entries just
2080 * disable all scanning. If there are entries
2081 * and we had both page and inquiry scanning
2082 * enabled then fall back to only page scanning.
2083 * Otherwise no changes are needed.
2084 */
2085 if (list_empty(&hdev->whitelist))
2086 scan = SCAN_DISABLED;
2087 else if (test_bit(HCI_ISCAN, &hdev->flags))
2088 scan = SCAN_PAGE;
2089 else
2090 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002091
2092 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002093 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002094 cancel_delayed_work(&hdev->discov_off);
2095 }
2096
2097 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2098 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002099
Johan Hedberg3bd27242014-07-28 20:53:58 +03002100no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002101 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002102 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2103 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002104 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002105
Johan Hedberg2b76f452013-03-15 17:07:04 -05002106 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002107 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002108 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002109 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002110 err = set_connectable_update_settings(hdev, sk,
2111 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002112 goto failed;
2113 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002114
2115failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002116 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002117 return err;
2118}
2119
Johan Hedbergb2939472014-07-30 09:22:23 +03002120static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002121 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002122{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002123 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002124 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002125 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002126
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002127 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002128
Johan Hedberga7e80f22013-01-09 16:05:19 +02002129 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002130 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2131 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002132
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002133 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002134
2135 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002136 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002137 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002138 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002139
Johan Hedbergb2939472014-07-30 09:22:23 +03002140 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002141 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002142 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002143
Marcel Holtmann55594352013-10-06 16:11:57 -07002144 if (changed)
2145 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002146
Marcel Holtmann55594352013-10-06 16:11:57 -07002147unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002148 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002149 return err;
2150}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002151
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002152static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2153 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002154{
2155 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002156 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002157 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002158 int err;
2159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002160 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002161
Johan Hedberge6fe7982013-10-02 15:45:22 +03002162 status = mgmt_bredr_support(hdev);
2163 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002164 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2165 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002166
Johan Hedberga7e80f22013-01-09 16:05:19 +02002167 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002168 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2169 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002170
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002171 hci_dev_lock(hdev);
2172
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002173 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002174 bool changed = false;
2175
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002176 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002177 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002178 changed = true;
2179 }
2180
2181 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2182 if (err < 0)
2183 goto failed;
2184
2185 if (changed)
2186 err = new_settings(hdev, sk);
2187
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002188 goto failed;
2189 }
2190
Johan Hedberg333ae952015-03-17 13:48:47 +02002191 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002192 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2193 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002194 goto failed;
2195 }
2196
2197 val = !!cp->val;
2198
2199 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2200 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2201 goto failed;
2202 }
2203
2204 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2205 if (!cmd) {
2206 err = -ENOMEM;
2207 goto failed;
2208 }
2209
2210 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2211 if (err < 0) {
2212 mgmt_pending_remove(cmd);
2213 goto failed;
2214 }
2215
2216failed:
2217 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002218 return err;
2219}
2220
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002221static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002222{
2223 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002224 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002225 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002226 int err;
2227
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002228 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002229
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002230 status = mgmt_bredr_support(hdev);
2231 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002232 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002233
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002234 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002235 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2236 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002237
Johan Hedberga7e80f22013-01-09 16:05:19 +02002238 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002239 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2240 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002241
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002242 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002243
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002244 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002245 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002246
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002247 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002248 changed = !hci_dev_test_and_set_flag(hdev,
2249 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002250 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002251 changed = hci_dev_test_and_clear_flag(hdev,
2252 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002253 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002254 changed = hci_dev_test_and_clear_flag(hdev,
2255 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002256 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002257 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002258 }
2259
2260 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2261 if (err < 0)
2262 goto failed;
2263
2264 if (changed)
2265 err = new_settings(hdev, sk);
2266
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002267 goto failed;
2268 }
2269
Johan Hedberg333ae952015-03-17 13:48:47 +02002270 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002271 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2272 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002273 goto failed;
2274 }
2275
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002276 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002277 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2278 goto failed;
2279 }
2280
2281 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2282 if (!cmd) {
2283 err = -ENOMEM;
2284 goto failed;
2285 }
2286
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002287 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002288 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2289 sizeof(cp->val), &cp->val);
2290
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002291 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002292 if (err < 0) {
2293 mgmt_pending_remove(cmd);
2294 goto failed;
2295 }
2296
2297failed:
2298 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002299 return err;
2300}
2301
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002302static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002303{
2304 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002305 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002306 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002307 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002309 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002310
Johan Hedberge6fe7982013-10-02 15:45:22 +03002311 status = mgmt_bredr_support(hdev);
2312 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002313 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002314
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002315 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002316 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2317 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002318
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002319 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002320 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2321 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002322
Johan Hedberga7e80f22013-01-09 16:05:19 +02002323 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002324 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2325 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002326
Marcel Holtmannee392692013-10-01 22:59:23 -07002327 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002328
Johan Hedberg333ae952015-03-17 13:48:47 +02002329 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002330 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2331 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002332 goto unlock;
2333 }
2334
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002335 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002336 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002337 } else {
2338 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002339 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2340 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002341 goto unlock;
2342 }
2343
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002344 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002345 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002346
2347 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2348 if (err < 0)
2349 goto unlock;
2350
2351 if (changed)
2352 err = new_settings(hdev, sk);
2353
2354unlock:
2355 hci_dev_unlock(hdev);
2356 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002357}
2358
Marcel Holtmann1904a852015-01-11 13:50:44 -08002359static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002360{
2361 struct cmd_lookup match = { NULL, hdev };
2362
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302363 hci_dev_lock(hdev);
2364
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002365 if (status) {
2366 u8 mgmt_err = mgmt_status(status);
2367
2368 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2369 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302370 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002371 }
2372
2373 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2374
2375 new_settings(hdev, match.sk);
2376
2377 if (match.sk)
2378 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002379
2380 /* Make sure the controller has a good default for
2381 * advertising data. Restrict the update to when LE
2382 * has actually been enabled. During power on, the
2383 * update in powered_update_hci will take care of it.
2384 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002385 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002386 struct hci_request req;
2387
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002388 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002389 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002390 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002391 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002392 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002393 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302394
2395unlock:
2396 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002397}
2398
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002399static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002400{
2401 struct mgmt_mode *cp = data;
2402 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002403 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002404 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002405 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002406 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002407
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002409
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002410 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002411 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2412 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002413
Johan Hedberga7e80f22013-01-09 16:05:19 +02002414 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002415 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2416 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002417
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002418 /* Bluetooth single mode LE only controllers or dual-mode
2419 * controllers configured as LE only devices, do not allow
2420 * switching LE off. These have either LE enabled explicitly
2421 * or BR/EDR has been previously switched off.
2422 *
2423 * When trying to enable an already enabled LE, then gracefully
2424 * send a positive response. Trying to disable it however will
2425 * result into rejection.
2426 */
2427 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2428 if (cp->val == 0x01)
2429 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2430
Johan Hedberga69e8372015-03-06 21:08:53 +02002431 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2432 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002433 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002434
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002435 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002436
2437 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002438 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002439
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002440 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002441 bool changed = false;
2442
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002443 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002444 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002445 changed = true;
2446 }
2447
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002448 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002449 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002450 changed = true;
2451 }
2452
Johan Hedberg06199cf2012-02-22 16:37:11 +02002453 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2454 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002455 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002456
2457 if (changed)
2458 err = new_settings(hdev, sk);
2459
Johan Hedberg1de028c2012-02-29 19:55:35 -08002460 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002461 }
2462
Johan Hedberg333ae952015-03-17 13:48:47 +02002463 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2464 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002465 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2466 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002467 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002468 }
2469
2470 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2471 if (!cmd) {
2472 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002473 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002474 }
2475
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002476 hci_req_init(&req, hdev);
2477
Johan Hedberg06199cf2012-02-22 16:37:11 +02002478 memset(&hci_cp, 0, sizeof(hci_cp));
2479
2480 if (val) {
2481 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002482 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002483 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002484 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002485 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002486 }
2487
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002488 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2489 &hci_cp);
2490
2491 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302492 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002493 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002494
Johan Hedberg1de028c2012-02-29 19:55:35 -08002495unlock:
2496 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002497 return err;
2498}
2499
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002500/* This is a helper function to test for pending mgmt commands that can
2501 * cause CoD or EIR HCI commands. We can only allow one such pending
2502 * mgmt command at a time since otherwise we cannot easily track what
2503 * the current values are, will be, and based on that calculate if a new
2504 * HCI command needs to be sent and if yes with what value.
2505 */
2506static bool pending_eir_or_class(struct hci_dev *hdev)
2507{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002508 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002509
2510 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2511 switch (cmd->opcode) {
2512 case MGMT_OP_ADD_UUID:
2513 case MGMT_OP_REMOVE_UUID:
2514 case MGMT_OP_SET_DEV_CLASS:
2515 case MGMT_OP_SET_POWERED:
2516 return true;
2517 }
2518 }
2519
2520 return false;
2521}
2522
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002523static const u8 bluetooth_base_uuid[] = {
2524 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2525 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2526};
2527
2528static u8 get_uuid_size(const u8 *uuid)
2529{
2530 u32 val;
2531
2532 if (memcmp(uuid, bluetooth_base_uuid, 12))
2533 return 128;
2534
2535 val = get_unaligned_le32(&uuid[12]);
2536 if (val > 0xffff)
2537 return 32;
2538
2539 return 16;
2540}
2541
Johan Hedberg92da6092013-03-15 17:06:55 -05002542static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2543{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002544 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002545
2546 hci_dev_lock(hdev);
2547
Johan Hedberg333ae952015-03-17 13:48:47 +02002548 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002549 if (!cmd)
2550 goto unlock;
2551
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002552 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2553 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002554
2555 mgmt_pending_remove(cmd);
2556
2557unlock:
2558 hci_dev_unlock(hdev);
2559}
2560
Marcel Holtmann1904a852015-01-11 13:50:44 -08002561static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002562{
2563 BT_DBG("status 0x%02x", status);
2564
2565 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2566}
2567
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002568static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002569{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002570 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002571 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002572 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002573 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002574 int err;
2575
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002576 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002577
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002578 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002579
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002580 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002581 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2582 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002583 goto failed;
2584 }
2585
Andre Guedes92c4c202012-06-07 19:05:44 -03002586 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002587 if (!uuid) {
2588 err = -ENOMEM;
2589 goto failed;
2590 }
2591
2592 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002593 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002594 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002595
Johan Hedbergde66aa62013-01-27 00:31:27 +02002596 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002597
Johan Hedberg890ea892013-03-15 17:06:52 -05002598 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002599
Johan Hedberg890ea892013-03-15 17:06:52 -05002600 update_class(&req);
2601 update_eir(&req);
2602
Johan Hedberg92da6092013-03-15 17:06:55 -05002603 err = hci_req_run(&req, add_uuid_complete);
2604 if (err < 0) {
2605 if (err != -ENODATA)
2606 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002607
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002608 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2609 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002610 goto failed;
2611 }
2612
2613 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002614 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002615 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002616 goto failed;
2617 }
2618
2619 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002620
2621failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002622 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002623 return err;
2624}
2625
Johan Hedberg24b78d02012-02-23 23:24:30 +02002626static bool enable_service_cache(struct hci_dev *hdev)
2627{
2628 if (!hdev_is_powered(hdev))
2629 return false;
2630
Marcel Holtmann238be782015-03-13 02:11:06 -07002631 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002632 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2633 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002634 return true;
2635 }
2636
2637 return false;
2638}
2639
Marcel Holtmann1904a852015-01-11 13:50:44 -08002640static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002641{
2642 BT_DBG("status 0x%02x", status);
2643
2644 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2645}
2646
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002647static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002648 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002649{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002650 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002651 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002652 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002653 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 -05002654 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002655 int err, found;
2656
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002657 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002658
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002659 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002660
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002661 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002662 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2663 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002664 goto unlock;
2665 }
2666
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002667 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002668 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002669
Johan Hedberg24b78d02012-02-23 23:24:30 +02002670 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002671 err = mgmt_cmd_complete(sk, hdev->id,
2672 MGMT_OP_REMOVE_UUID,
2673 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002674 goto unlock;
2675 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002676
Johan Hedberg9246a862012-02-23 21:33:16 +02002677 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002678 }
2679
2680 found = 0;
2681
Johan Hedberg056341c2013-01-27 00:31:30 +02002682 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002683 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2684 continue;
2685
2686 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002687 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002688 found++;
2689 }
2690
2691 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002692 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2693 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002694 goto unlock;
2695 }
2696
Johan Hedberg9246a862012-02-23 21:33:16 +02002697update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002698 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002699
Johan Hedberg890ea892013-03-15 17:06:52 -05002700 update_class(&req);
2701 update_eir(&req);
2702
Johan Hedberg92da6092013-03-15 17:06:55 -05002703 err = hci_req_run(&req, remove_uuid_complete);
2704 if (err < 0) {
2705 if (err != -ENODATA)
2706 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002707
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002708 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2709 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002710 goto unlock;
2711 }
2712
2713 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002714 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002715 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002716 goto unlock;
2717 }
2718
2719 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002720
2721unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002722 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002723 return err;
2724}
2725
Marcel Holtmann1904a852015-01-11 13:50:44 -08002726static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002727{
2728 BT_DBG("status 0x%02x", status);
2729
2730 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2731}
2732
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002733static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002734 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002735{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002736 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002737 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002738 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002739 int err;
2740
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002741 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002742
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002743 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002744 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2745 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002746
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002747 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002748
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002749 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002750 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2751 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002752 goto unlock;
2753 }
2754
2755 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002756 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2757 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002758 goto unlock;
2759 }
2760
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002761 hdev->major_class = cp->major;
2762 hdev->minor_class = cp->minor;
2763
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002764 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002765 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2766 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002767 goto unlock;
2768 }
2769
Johan Hedberg890ea892013-03-15 17:06:52 -05002770 hci_req_init(&req, hdev);
2771
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002772 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002773 hci_dev_unlock(hdev);
2774 cancel_delayed_work_sync(&hdev->service_cache);
2775 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002776 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002777 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002778
Johan Hedberg890ea892013-03-15 17:06:52 -05002779 update_class(&req);
2780
Johan Hedberg92da6092013-03-15 17:06:55 -05002781 err = hci_req_run(&req, set_class_complete);
2782 if (err < 0) {
2783 if (err != -ENODATA)
2784 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002785
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002786 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2787 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002788 goto unlock;
2789 }
2790
2791 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002792 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002793 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002794 goto unlock;
2795 }
2796
2797 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002798
Johan Hedbergb5235a62012-02-21 14:32:24 +02002799unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002800 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002801 return err;
2802}
2803
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002804static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002805 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002806{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002807 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002808 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2809 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002810 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002811 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002812 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002813
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002814 BT_DBG("request for %s", hdev->name);
2815
2816 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002817 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2818 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002819
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002820 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002821 if (key_count > max_key_count) {
2822 BT_ERR("load_link_keys: too big key_count value %u",
2823 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002824 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2825 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002826 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002827
Johan Hedberg86742e12011-11-07 23:13:38 +02002828 expected_len = sizeof(*cp) + key_count *
2829 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002830 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002831 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002832 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002833 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2834 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002835 }
2836
Johan Hedberg4ae14302013-01-20 14:27:13 +02002837 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002838 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2839 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002840
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002841 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002842 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002843
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002844 for (i = 0; i < key_count; i++) {
2845 struct mgmt_link_key_info *key = &cp->keys[i];
2846
Marcel Holtmann8e991132014-01-10 02:07:25 -08002847 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002848 return mgmt_cmd_status(sk, hdev->id,
2849 MGMT_OP_LOAD_LINK_KEYS,
2850 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002851 }
2852
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002853 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002854
2855 hci_link_keys_clear(hdev);
2856
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002857 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002858 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002859 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002860 changed = hci_dev_test_and_clear_flag(hdev,
2861 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002862
2863 if (changed)
2864 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002865
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002866 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002867 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002868
Johan Hedberg58e92932014-06-24 14:00:26 +03002869 /* Always ignore debug keys and require a new pairing if
2870 * the user wants to use them.
2871 */
2872 if (key->type == HCI_LK_DEBUG_COMBINATION)
2873 continue;
2874
Johan Hedberg7652ff62014-06-24 13:15:49 +03002875 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2876 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002877 }
2878
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002879 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002880
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002881 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002882
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002883 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002884}
2885
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002886static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002887 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002888{
2889 struct mgmt_ev_device_unpaired ev;
2890
2891 bacpy(&ev.addr.bdaddr, bdaddr);
2892 ev.addr.type = addr_type;
2893
2894 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002895 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002896}
2897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002898static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002899 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002900{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002901 struct mgmt_cp_unpair_device *cp = data;
2902 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002903 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002904 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002905 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002906 int err;
2907
Johan Hedberga8a1d192011-11-10 15:54:38 +02002908 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002909 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2910 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002911
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002912 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002913 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2914 MGMT_STATUS_INVALID_PARAMS,
2915 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002916
Johan Hedberg118da702013-01-20 14:27:20 +02002917 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002918 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2919 MGMT_STATUS_INVALID_PARAMS,
2920 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002921
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002922 hci_dev_lock(hdev);
2923
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002924 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002925 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2926 MGMT_STATUS_NOT_POWERED, &rp,
2927 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002928 goto unlock;
2929 }
2930
Johan Hedberge0b2b272014-02-18 17:14:31 +02002931 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002932 /* If disconnection is requested, then look up the
2933 * connection. If the remote device is connected, it
2934 * will be later used to terminate the link.
2935 *
2936 * Setting it to NULL explicitly will cause no
2937 * termination of the link.
2938 */
2939 if (cp->disconnect)
2940 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2941 &cp->addr.bdaddr);
2942 else
2943 conn = NULL;
2944
Johan Hedberg124f6e32012-02-09 13:50:12 +02002945 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002946 } else {
2947 u8 addr_type;
2948
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002949 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2950 &cp->addr.bdaddr);
2951 if (conn) {
2952 /* Defer clearing up the connection parameters
2953 * until closing to give a chance of keeping
2954 * them if a repairing happens.
2955 */
2956 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2957
2958 /* If disconnection is not requested, then
2959 * clear the connection variable so that the
2960 * link is not terminated.
2961 */
2962 if (!cp->disconnect)
2963 conn = NULL;
2964 }
2965
Johan Hedberge0b2b272014-02-18 17:14:31 +02002966 if (cp->addr.type == BDADDR_LE_PUBLIC)
2967 addr_type = ADDR_LE_DEV_PUBLIC;
2968 else
2969 addr_type = ADDR_LE_DEV_RANDOM;
2970
Johan Hedberga7ec7332014-02-18 17:14:35 +02002971 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2972
Johan Hedberge0b2b272014-02-18 17:14:31 +02002973 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2974 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002975
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002976 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002977 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2978 MGMT_STATUS_NOT_PAIRED, &rp,
2979 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002980 goto unlock;
2981 }
2982
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002983 /* If the connection variable is set, then termination of the
2984 * link is requested.
2985 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002986 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002987 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2988 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002989 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002990 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002991 }
2992
Johan Hedberg124f6e32012-02-09 13:50:12 +02002993 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002994 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002995 if (!cmd) {
2996 err = -ENOMEM;
2997 goto unlock;
2998 }
2999
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003000 cmd->cmd_complete = addr_cmd_complete;
3001
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003002 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003003 dc.reason = 0x13; /* Remote User Terminated Connection */
3004 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3005 if (err < 0)
3006 mgmt_pending_remove(cmd);
3007
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003008unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003009 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003010 return err;
3011}
3012
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003013static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003014 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003015{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003016 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003017 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003018 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003019 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003020 int err;
3021
3022 BT_DBG("");
3023
Johan Hedberg06a63b12013-01-20 14:27:21 +02003024 memset(&rp, 0, sizeof(rp));
3025 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3026 rp.addr.type = cp->addr.type;
3027
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003028 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003029 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3030 MGMT_STATUS_INVALID_PARAMS,
3031 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003032
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003033 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003034
3035 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003036 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3037 MGMT_STATUS_NOT_POWERED, &rp,
3038 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003039 goto failed;
3040 }
3041
Johan Hedberg333ae952015-03-17 13:48:47 +02003042 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003043 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3044 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003045 goto failed;
3046 }
3047
Andre Guedes591f47f2012-04-24 21:02:49 -03003048 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003049 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3050 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003051 else
3052 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003053
Vishal Agarwalf9607272012-06-13 05:32:43 +05303054 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003055 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3056 MGMT_STATUS_NOT_CONNECTED, &rp,
3057 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003058 goto failed;
3059 }
3060
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003061 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003062 if (!cmd) {
3063 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003064 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003065 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003066
Johan Hedbergf5818c22014-12-05 13:36:02 +02003067 cmd->cmd_complete = generic_cmd_complete;
3068
Johan Hedberge3f2f922014-08-18 20:33:33 +03003069 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003070 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003071 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003072
3073failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003074 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003075 return err;
3076}
3077
Andre Guedes57c14772012-04-24 21:02:50 -03003078static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003079{
3080 switch (link_type) {
3081 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003082 switch (addr_type) {
3083 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003084 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003085
Johan Hedberg48264f02011-11-09 13:58:58 +02003086 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003087 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003088 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003089 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003090
Johan Hedberg4c659c32011-11-07 23:13:39 +02003091 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003092 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003093 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003094 }
3095}
3096
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003097static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3098 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003099{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003100 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003101 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003102 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003103 int err;
3104 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003105
3106 BT_DBG("");
3107
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003108 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003109
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003110 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003111 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3112 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003113 goto unlock;
3114 }
3115
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003116 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003117 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3118 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003119 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003120 }
3121
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003122 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003123 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003124 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003125 err = -ENOMEM;
3126 goto unlock;
3127 }
3128
Johan Hedberg2784eb42011-01-21 13:56:35 +02003129 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003130 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003131 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3132 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003133 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003134 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003135 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003136 continue;
3137 i++;
3138 }
3139
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003140 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003141
Johan Hedberg4c659c32011-11-07 23:13:39 +02003142 /* Recalculate length in case of filtered SCO connections, etc */
3143 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003144
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003145 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3146 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003147
Johan Hedberga38528f2011-01-22 06:46:43 +02003148 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003149
3150unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003151 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003152 return err;
3153}
3154
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003155static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003156 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003157{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003158 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003159 int err;
3160
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003161 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003162 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003163 if (!cmd)
3164 return -ENOMEM;
3165
Johan Hedbergd8457692012-02-17 14:24:57 +02003166 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003167 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003168 if (err < 0)
3169 mgmt_pending_remove(cmd);
3170
3171 return err;
3172}
3173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003174static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003175 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003176{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003177 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003178 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003179 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003180 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003181 int err;
3182
3183 BT_DBG("");
3184
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003185 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003186
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003187 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003188 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3189 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003190 goto failed;
3191 }
3192
Johan Hedbergd8457692012-02-17 14:24:57 +02003193 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003194 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003195 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3196 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003197 goto failed;
3198 }
3199
3200 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003201 struct mgmt_cp_pin_code_neg_reply ncp;
3202
3203 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003204
3205 BT_ERR("PIN code is not 16 bytes long");
3206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003207 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003208 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003209 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3210 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003211
3212 goto failed;
3213 }
3214
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003215 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003216 if (!cmd) {
3217 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003218 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003219 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003220
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003221 cmd->cmd_complete = addr_cmd_complete;
3222
Johan Hedbergd8457692012-02-17 14:24:57 +02003223 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003224 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003225 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003226
3227 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3228 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003229 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003230
3231failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003232 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003233 return err;
3234}
3235
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003236static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3237 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003238{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003239 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003240
3241 BT_DBG("");
3242
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003243 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003244 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3245 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003246
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003247 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003248
3249 hdev->io_capability = cp->io_capability;
3250
3251 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003252 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003253
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003254 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003255
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003256 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3257 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003258}
3259
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003260static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003261{
3262 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003263 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003264
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003265 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003266 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3267 continue;
3268
Johan Hedberge9a416b2011-02-19 12:05:56 -03003269 if (cmd->user_data != conn)
3270 continue;
3271
3272 return cmd;
3273 }
3274
3275 return NULL;
3276}
3277
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003278static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003279{
3280 struct mgmt_rp_pair_device rp;
3281 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003282 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003283
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003284 bacpy(&rp.addr.bdaddr, &conn->dst);
3285 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003286
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003287 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3288 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003289
3290 /* So we don't get further callbacks for this connection */
3291 conn->connect_cfm_cb = NULL;
3292 conn->security_cfm_cb = NULL;
3293 conn->disconn_cfm_cb = NULL;
3294
David Herrmann76a68ba2013-04-06 20:28:37 +02003295 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003296
3297 /* The device is paired so there is no need to remove
3298 * its connection parameters anymore.
3299 */
3300 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003301
3302 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003303
3304 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003305}
3306
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003307void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3308{
3309 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003310 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003311
3312 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003313 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003314 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003315 mgmt_pending_remove(cmd);
3316 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003317}
3318
Johan Hedberge9a416b2011-02-19 12:05:56 -03003319static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3320{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003321 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003322
3323 BT_DBG("status %u", status);
3324
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003325 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003326 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003327 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003328 return;
3329 }
3330
3331 cmd->cmd_complete(cmd, mgmt_status(status));
3332 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003333}
3334
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003335static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303336{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003337 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303338
3339 BT_DBG("status %u", status);
3340
3341 if (!status)
3342 return;
3343
3344 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003345 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303346 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003347 return;
3348 }
3349
3350 cmd->cmd_complete(cmd, mgmt_status(status));
3351 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303352}
3353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003354static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003355 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003356{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003357 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003358 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003359 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003360 u8 sec_level, auth_type;
3361 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003362 int err;
3363
3364 BT_DBG("");
3365
Szymon Jancf950a30e2013-01-18 12:48:07 +01003366 memset(&rp, 0, sizeof(rp));
3367 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3368 rp.addr.type = cp->addr.type;
3369
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003370 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003371 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3372 MGMT_STATUS_INVALID_PARAMS,
3373 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003374
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003375 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003376 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3377 MGMT_STATUS_INVALID_PARAMS,
3378 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003379
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003380 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003381
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003382 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003383 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3384 MGMT_STATUS_NOT_POWERED, &rp,
3385 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003386 goto unlock;
3387 }
3388
Johan Hedberg55e76b32015-03-10 22:34:40 +02003389 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3390 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3391 MGMT_STATUS_ALREADY_PAIRED, &rp,
3392 sizeof(rp));
3393 goto unlock;
3394 }
3395
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003396 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003397 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003398
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003399 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003400 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3401 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003402 } else {
3403 u8 addr_type;
3404
3405 /* Convert from L2CAP channel address type to HCI address type
3406 */
3407 if (cp->addr.type == BDADDR_LE_PUBLIC)
3408 addr_type = ADDR_LE_DEV_PUBLIC;
3409 else
3410 addr_type = ADDR_LE_DEV_RANDOM;
3411
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003412 /* When pairing a new device, it is expected to remember
3413 * this device for future connections. Adding the connection
3414 * parameter information ahead of time allows tracking
3415 * of the slave preferred values and will speed up any
3416 * further connection establishment.
3417 *
3418 * If connection parameters already exist, then they
3419 * will be kept and this function does nothing.
3420 */
3421 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3422
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003423 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003424 sec_level, HCI_LE_CONN_TIMEOUT,
3425 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003426 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003427
Ville Tervo30e76272011-02-22 16:10:53 -03003428 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003429 int status;
3430
3431 if (PTR_ERR(conn) == -EBUSY)
3432 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003433 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3434 status = MGMT_STATUS_NOT_SUPPORTED;
3435 else if (PTR_ERR(conn) == -ECONNREFUSED)
3436 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003437 else
3438 status = MGMT_STATUS_CONNECT_FAILED;
3439
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003440 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3441 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003442 goto unlock;
3443 }
3444
3445 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003446 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003447 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3448 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003449 goto unlock;
3450 }
3451
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003452 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003453 if (!cmd) {
3454 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003455 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003456 goto unlock;
3457 }
3458
Johan Hedberg04ab2742014-12-05 13:36:04 +02003459 cmd->cmd_complete = pairing_complete;
3460
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003461 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003462 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003463 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003464 conn->security_cfm_cb = pairing_complete_cb;
3465 conn->disconn_cfm_cb = pairing_complete_cb;
3466 } else {
3467 conn->connect_cfm_cb = le_pairing_complete_cb;
3468 conn->security_cfm_cb = le_pairing_complete_cb;
3469 conn->disconn_cfm_cb = le_pairing_complete_cb;
3470 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003471
Johan Hedberge9a416b2011-02-19 12:05:56 -03003472 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003473 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003474
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003475 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003476 hci_conn_security(conn, sec_level, auth_type, true)) {
3477 cmd->cmd_complete(cmd, 0);
3478 mgmt_pending_remove(cmd);
3479 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003480
3481 err = 0;
3482
3483unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003484 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003485 return err;
3486}
3487
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003488static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3489 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003490{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003491 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003492 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003493 struct hci_conn *conn;
3494 int err;
3495
3496 BT_DBG("");
3497
Johan Hedberg28424702012-02-02 04:02:29 +02003498 hci_dev_lock(hdev);
3499
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003500 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003501 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3502 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003503 goto unlock;
3504 }
3505
Johan Hedberg333ae952015-03-17 13:48:47 +02003506 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003507 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003508 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3509 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003510 goto unlock;
3511 }
3512
3513 conn = cmd->user_data;
3514
3515 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003516 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3517 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003518 goto unlock;
3519 }
3520
Johan Hedberga511b352014-12-11 21:45:45 +02003521 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3522 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003523
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003524 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3525 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003526unlock:
3527 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003528 return err;
3529}
3530
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003531static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003532 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003533 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003534{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003535 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003536 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003537 int err;
3538
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003539 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003540
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003541 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003542 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3543 MGMT_STATUS_NOT_POWERED, addr,
3544 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003545 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003546 }
3547
Johan Hedberg1707c602013-03-15 17:07:15 -05003548 if (addr->type == BDADDR_BREDR)
3549 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003550 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003551 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003552
Johan Hedberg272d90d2012-02-09 15:26:12 +02003553 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003554 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3555 MGMT_STATUS_NOT_CONNECTED, addr,
3556 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003557 goto done;
3558 }
3559
Johan Hedberg1707c602013-03-15 17:07:15 -05003560 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003561 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003562 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003563 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3564 MGMT_STATUS_SUCCESS, addr,
3565 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003566 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003567 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3568 MGMT_STATUS_FAILED, addr,
3569 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003570
Brian Gix47c15e22011-11-16 13:53:14 -08003571 goto done;
3572 }
3573
Johan Hedberg1707c602013-03-15 17:07:15 -05003574 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003575 if (!cmd) {
3576 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003577 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003578 }
3579
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003580 cmd->cmd_complete = addr_cmd_complete;
3581
Brian Gix0df4c182011-11-16 13:53:13 -08003582 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003583 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3584 struct hci_cp_user_passkey_reply cp;
3585
Johan Hedberg1707c602013-03-15 17:07:15 -05003586 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003587 cp.passkey = passkey;
3588 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3589 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003590 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3591 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003592
Johan Hedberga664b5b2011-02-19 12:06:02 -03003593 if (err < 0)
3594 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003595
Brian Gix0df4c182011-11-16 13:53:13 -08003596done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003597 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003598 return err;
3599}
3600
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303601static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3602 void *data, u16 len)
3603{
3604 struct mgmt_cp_pin_code_neg_reply *cp = data;
3605
3606 BT_DBG("");
3607
Johan Hedberg1707c602013-03-15 17:07:15 -05003608 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303609 MGMT_OP_PIN_CODE_NEG_REPLY,
3610 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3611}
3612
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003613static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3614 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003615{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003616 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003617
3618 BT_DBG("");
3619
3620 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003621 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3622 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003623
Johan Hedberg1707c602013-03-15 17:07:15 -05003624 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003625 MGMT_OP_USER_CONFIRM_REPLY,
3626 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003627}
3628
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003629static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003630 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003631{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003632 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003633
3634 BT_DBG("");
3635
Johan Hedberg1707c602013-03-15 17:07:15 -05003636 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003637 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3638 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003639}
3640
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003641static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3642 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003643{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003644 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003645
3646 BT_DBG("");
3647
Johan Hedberg1707c602013-03-15 17:07:15 -05003648 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003649 MGMT_OP_USER_PASSKEY_REPLY,
3650 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003651}
3652
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003653static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003654 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003655{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003656 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003657
3658 BT_DBG("");
3659
Johan Hedberg1707c602013-03-15 17:07:15 -05003660 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003661 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3662 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003663}
3664
Johan Hedberg13928972013-03-15 17:07:00 -05003665static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003666{
Johan Hedberg13928972013-03-15 17:07:00 -05003667 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003668 struct hci_cp_write_local_name cp;
3669
Johan Hedberg13928972013-03-15 17:07:00 -05003670 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003671
Johan Hedberg890ea892013-03-15 17:06:52 -05003672 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003673}
3674
Marcel Holtmann1904a852015-01-11 13:50:44 -08003675static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003676{
3677 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003678 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003679
3680 BT_DBG("status 0x%02x", status);
3681
3682 hci_dev_lock(hdev);
3683
Johan Hedberg333ae952015-03-17 13:48:47 +02003684 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003685 if (!cmd)
3686 goto unlock;
3687
3688 cp = cmd->param;
3689
3690 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003691 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3692 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003693 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003694 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3695 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003696
3697 mgmt_pending_remove(cmd);
3698
3699unlock:
3700 hci_dev_unlock(hdev);
3701}
3702
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003703static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003704 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003705{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003706 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003707 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003708 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003709 int err;
3710
3711 BT_DBG("");
3712
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003713 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003714
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003715 /* If the old values are the same as the new ones just return a
3716 * direct command complete event.
3717 */
3718 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3719 !memcmp(hdev->short_name, cp->short_name,
3720 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003721 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3722 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003723 goto failed;
3724 }
3725
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003726 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003727
Johan Hedbergb5235a62012-02-21 14:32:24 +02003728 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003729 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003730
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003731 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3732 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003733 if (err < 0)
3734 goto failed;
3735
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003736 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3737 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003738
Johan Hedbergb5235a62012-02-21 14:32:24 +02003739 goto failed;
3740 }
3741
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003742 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003743 if (!cmd) {
3744 err = -ENOMEM;
3745 goto failed;
3746 }
3747
Johan Hedberg13928972013-03-15 17:07:00 -05003748 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3749
Johan Hedberg890ea892013-03-15 17:06:52 -05003750 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003751
3752 if (lmp_bredr_capable(hdev)) {
3753 update_name(&req);
3754 update_eir(&req);
3755 }
3756
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003757 /* The name is stored in the scan response data and so
3758 * no need to udpate the advertising data here.
3759 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003760 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003761 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003762
Johan Hedberg13928972013-03-15 17:07:00 -05003763 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003764 if (err < 0)
3765 mgmt_pending_remove(cmd);
3766
3767failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003768 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003769 return err;
3770}
3771
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003772static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3773 u16 opcode, struct sk_buff *skb)
3774{
3775 struct mgmt_rp_read_local_oob_data mgmt_rp;
3776 size_t rp_size = sizeof(mgmt_rp);
3777 struct mgmt_pending_cmd *cmd;
3778
3779 BT_DBG("%s status %u", hdev->name, status);
3780
3781 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3782 if (!cmd)
3783 return;
3784
3785 if (status || !skb) {
3786 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3787 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3788 goto remove;
3789 }
3790
3791 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3792
3793 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3794 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3795
3796 if (skb->len < sizeof(*rp)) {
3797 mgmt_cmd_status(cmd->sk, hdev->id,
3798 MGMT_OP_READ_LOCAL_OOB_DATA,
3799 MGMT_STATUS_FAILED);
3800 goto remove;
3801 }
3802
3803 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3804 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3805
3806 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3807 } else {
3808 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3809
3810 if (skb->len < sizeof(*rp)) {
3811 mgmt_cmd_status(cmd->sk, hdev->id,
3812 MGMT_OP_READ_LOCAL_OOB_DATA,
3813 MGMT_STATUS_FAILED);
3814 goto remove;
3815 }
3816
3817 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3818 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3819
3820 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3821 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3822 }
3823
3824 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3825 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3826
3827remove:
3828 mgmt_pending_remove(cmd);
3829}
3830
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003831static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003832 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003833{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003834 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003835 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003836 int err;
3837
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003838 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003839
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003840 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003841
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003842 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003843 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3844 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003845 goto unlock;
3846 }
3847
Andre Guedes9a1a1992012-07-24 15:03:48 -03003848 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003849 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3850 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003851 goto unlock;
3852 }
3853
Johan Hedberg333ae952015-03-17 13:48:47 +02003854 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003855 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3856 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003857 goto unlock;
3858 }
3859
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003860 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003861 if (!cmd) {
3862 err = -ENOMEM;
3863 goto unlock;
3864 }
3865
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003866 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003867
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003868 if (bredr_sc_enabled(hdev))
3869 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3870 else
3871 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3872
3873 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003874 if (err < 0)
3875 mgmt_pending_remove(cmd);
3876
3877unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003878 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003879 return err;
3880}
3881
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003882static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003883 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003884{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003885 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003886 int err;
3887
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003888 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003889
Johan Hedberg5d57e792015-01-23 10:10:38 +02003890 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003891 return mgmt_cmd_complete(sk, hdev->id,
3892 MGMT_OP_ADD_REMOTE_OOB_DATA,
3893 MGMT_STATUS_INVALID_PARAMS,
3894 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003895
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003896 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003897
Marcel Holtmannec109112014-01-10 02:07:30 -08003898 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3899 struct mgmt_cp_add_remote_oob_data *cp = data;
3900 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003901
Johan Hedbergc19a4952014-11-17 20:52:19 +02003902 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003903 err = mgmt_cmd_complete(sk, hdev->id,
3904 MGMT_OP_ADD_REMOTE_OOB_DATA,
3905 MGMT_STATUS_INVALID_PARAMS,
3906 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003907 goto unlock;
3908 }
3909
Marcel Holtmannec109112014-01-10 02:07:30 -08003910 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003911 cp->addr.type, cp->hash,
3912 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003913 if (err < 0)
3914 status = MGMT_STATUS_FAILED;
3915 else
3916 status = MGMT_STATUS_SUCCESS;
3917
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003918 err = mgmt_cmd_complete(sk, hdev->id,
3919 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3920 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003921 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3922 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003923 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003924 u8 status;
3925
Johan Hedberg86df9202014-10-26 20:52:27 +01003926 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003927 /* Enforce zero-valued 192-bit parameters as
3928 * long as legacy SMP OOB isn't implemented.
3929 */
3930 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3931 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003932 err = mgmt_cmd_complete(sk, hdev->id,
3933 MGMT_OP_ADD_REMOTE_OOB_DATA,
3934 MGMT_STATUS_INVALID_PARAMS,
3935 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003936 goto unlock;
3937 }
3938
Johan Hedberg86df9202014-10-26 20:52:27 +01003939 rand192 = NULL;
3940 hash192 = NULL;
3941 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003942 /* In case one of the P-192 values is set to zero,
3943 * then just disable OOB data for P-192.
3944 */
3945 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3946 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3947 rand192 = NULL;
3948 hash192 = NULL;
3949 } else {
3950 rand192 = cp->rand192;
3951 hash192 = cp->hash192;
3952 }
3953 }
3954
3955 /* In case one of the P-256 values is set to zero, then just
3956 * disable OOB data for P-256.
3957 */
3958 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3959 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3960 rand256 = NULL;
3961 hash256 = NULL;
3962 } else {
3963 rand256 = cp->rand256;
3964 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003965 }
3966
Johan Hedberg81328d52014-10-26 20:33:47 +01003967 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003968 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003969 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003970 if (err < 0)
3971 status = MGMT_STATUS_FAILED;
3972 else
3973 status = MGMT_STATUS_SUCCESS;
3974
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003975 err = mgmt_cmd_complete(sk, hdev->id,
3976 MGMT_OP_ADD_REMOTE_OOB_DATA,
3977 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003978 } else {
3979 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003980 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3981 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003982 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003983
Johan Hedbergc19a4952014-11-17 20:52:19 +02003984unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003985 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003986 return err;
3987}
3988
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003989static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003990 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003991{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003992 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003993 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003994 int err;
3995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003996 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003997
Johan Hedbergc19a4952014-11-17 20:52:19 +02003998 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003999 return mgmt_cmd_complete(sk, hdev->id,
4000 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4001 MGMT_STATUS_INVALID_PARAMS,
4002 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004003
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004004 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004005
Johan Hedbergeedbd582014-11-15 09:34:23 +02004006 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4007 hci_remote_oob_data_clear(hdev);
4008 status = MGMT_STATUS_SUCCESS;
4009 goto done;
4010 }
4011
Johan Hedberg6928a922014-10-26 20:46:09 +01004012 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004013 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004014 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004015 else
Szymon Janca6785be2012-12-13 15:11:21 +01004016 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004017
Johan Hedbergeedbd582014-11-15 09:34:23 +02004018done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004019 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4020 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004021
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004022 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004023 return err;
4024}
4025
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004026static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
4027{
4028 struct hci_dev *hdev = req->hdev;
4029 struct hci_cp_inquiry cp;
4030 /* General inquiry access code (GIAC) */
4031 u8 lap[3] = { 0x33, 0x8b, 0x9e };
4032
4033 *status = mgmt_bredr_support(hdev);
4034 if (*status)
4035 return false;
4036
4037 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
4038 *status = MGMT_STATUS_BUSY;
4039 return false;
4040 }
4041
4042 hci_inquiry_cache_flush(hdev);
4043
4044 memset(&cp, 0, sizeof(cp));
4045 memcpy(&cp.lap, lap, sizeof(cp.lap));
4046 cp.length = DISCOV_BREDR_INQUIRY_LEN;
4047
4048 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4049
4050 return true;
4051}
4052
4053static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004054{
Marcel Holtmann80190442014-12-04 11:36:36 +01004055 struct hci_dev *hdev = req->hdev;
4056 struct hci_cp_le_set_scan_param param_cp;
4057 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004058 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004059 int err;
4060
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004061 *status = mgmt_le_support(hdev);
4062 if (*status)
4063 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004064
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004065 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4066 /* Don't let discovery abort an outgoing connection attempt
4067 * that's using directed advertising.
4068 */
4069 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4070 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004071 return false;
4072 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004073
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004074 disable_advertising(req);
4075 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004076
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004077 /* If controller is scanning, it means the background scanning is
4078 * running. Thus, we should temporarily stop it in order to set the
4079 * discovery scanning parameters.
4080 */
4081 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4082 hci_req_add_le_scan_disable(req);
4083
4084 /* All active scans will be done with either a resolvable private
4085 * address (when privacy feature has been enabled) or non-resolvable
4086 * private address.
4087 */
4088 err = hci_update_random_address(req, true, &own_addr_type);
4089 if (err < 0) {
4090 *status = MGMT_STATUS_FAILED;
4091 return false;
4092 }
4093
4094 memset(&param_cp, 0, sizeof(param_cp));
4095 param_cp.type = LE_SCAN_ACTIVE;
4096 param_cp.interval = cpu_to_le16(interval);
4097 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4098 param_cp.own_address_type = own_addr_type;
4099
4100 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4101 &param_cp);
4102
4103 memset(&enable_cp, 0, sizeof(enable_cp));
4104 enable_cp.enable = LE_SCAN_ENABLE;
4105 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4106
4107 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4108 &enable_cp);
4109
4110 return true;
4111}
4112
4113static bool trigger_discovery(struct hci_request *req, u8 *status)
4114{
4115 struct hci_dev *hdev = req->hdev;
4116
4117 switch (hdev->discovery.type) {
4118 case DISCOV_TYPE_BREDR:
4119 if (!trigger_bredr_inquiry(req, status))
4120 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004121 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004122
Marcel Holtmann80190442014-12-04 11:36:36 +01004123 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004124 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4125 &hdev->quirks)) {
4126 /* During simultaneous discovery, we double LE scan
4127 * interval. We must leave some time for the controller
4128 * to do BR/EDR inquiry.
4129 */
4130 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4131 status))
4132 return false;
4133
4134 if (!trigger_bredr_inquiry(req, status))
4135 return false;
4136
4137 return true;
4138 }
4139
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004140 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004141 *status = MGMT_STATUS_NOT_SUPPORTED;
4142 return false;
4143 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004144 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004145
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004146 case DISCOV_TYPE_LE:
4147 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004148 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004149 break;
4150
4151 default:
4152 *status = MGMT_STATUS_INVALID_PARAMS;
4153 return false;
4154 }
4155
4156 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004157}
4158
Marcel Holtmann1904a852015-01-11 13:50:44 -08004159static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4160 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004161{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004162 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004163 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004164
Andre Guedes7c307722013-04-30 15:29:28 -03004165 BT_DBG("status %d", status);
4166
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004167 hci_dev_lock(hdev);
4168
Johan Hedberg333ae952015-03-17 13:48:47 +02004169 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004170 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004171 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004172
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004173 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004174 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004175 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004176 }
4177
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004178 if (status) {
4179 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4180 goto unlock;
4181 }
4182
Andre Guedes7c307722013-04-30 15:29:28 -03004183 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004184
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004185 /* If the scan involves LE scan, pick proper timeout to schedule
4186 * hdev->le_scan_disable that will stop it.
4187 */
Andre Guedes7c307722013-04-30 15:29:28 -03004188 switch (hdev->discovery.type) {
4189 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004190 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004191 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004192 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004193 /* When running simultaneous discovery, the LE scanning time
4194 * should occupy the whole discovery time sine BR/EDR inquiry
4195 * and LE scanning are scheduled by the controller.
4196 *
4197 * For interleaving discovery in comparison, BR/EDR inquiry
4198 * and LE scanning are done sequentially with separate
4199 * timeouts.
4200 */
4201 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4202 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4203 else
4204 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004205 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004206 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004207 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004208 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004209 default:
4210 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004211 timeout = 0;
4212 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004213 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004214
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004215 if (timeout) {
4216 /* When service discovery is used and the controller has
4217 * a strict duplicate filter, it is important to remember
4218 * the start and duration of the scan. This is required
4219 * for restarting scanning during the discovery phase.
4220 */
4221 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4222 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004223 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004224 hdev->discovery.scan_start = jiffies;
4225 hdev->discovery.scan_duration = timeout;
4226 }
4227
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004228 queue_delayed_work(hdev->workqueue,
4229 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004230 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004231
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004232unlock:
4233 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004234}
4235
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004236static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004237 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004238{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004239 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004240 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004241 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004242 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004243 int err;
4244
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004245 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004246
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004247 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004248
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004249 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004250 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4251 MGMT_STATUS_NOT_POWERED,
4252 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004253 goto failed;
4254 }
4255
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004256 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004257 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004258 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4259 MGMT_STATUS_BUSY, &cp->type,
4260 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004261 goto failed;
4262 }
4263
Johan Hedberg2922a942014-12-05 13:36:06 +02004264 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004265 if (!cmd) {
4266 err = -ENOMEM;
4267 goto failed;
4268 }
4269
Johan Hedberg2922a942014-12-05 13:36:06 +02004270 cmd->cmd_complete = generic_cmd_complete;
4271
Marcel Holtmann22078802014-12-05 11:45:22 +01004272 /* Clear the discovery filter first to free any previously
4273 * allocated memory for the UUID list.
4274 */
4275 hci_discovery_filter_clear(hdev);
4276
Andre Guedes4aab14e2012-02-17 20:39:36 -03004277 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004278 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004279
Andre Guedes7c307722013-04-30 15:29:28 -03004280 hci_req_init(&req, hdev);
4281
Marcel Holtmann80190442014-12-04 11:36:36 +01004282 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004283 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4284 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004285 mgmt_pending_remove(cmd);
4286 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004287 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004288
Andre Guedes7c307722013-04-30 15:29:28 -03004289 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004290 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004291 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004292 goto failed;
4293 }
4294
4295 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004296
4297failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004298 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004299 return err;
4300}
4301
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004302static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4303 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004304{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004305 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4306 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004307}
4308
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004309static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4310 void *data, u16 len)
4311{
4312 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004313 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004314 struct hci_request req;
4315 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4316 u16 uuid_count, expected_len;
4317 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004318 int err;
4319
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004320 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004321
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004322 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004323
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004324 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004325 err = mgmt_cmd_complete(sk, hdev->id,
4326 MGMT_OP_START_SERVICE_DISCOVERY,
4327 MGMT_STATUS_NOT_POWERED,
4328 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004329 goto failed;
4330 }
4331
4332 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004333 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004334 err = mgmt_cmd_complete(sk, hdev->id,
4335 MGMT_OP_START_SERVICE_DISCOVERY,
4336 MGMT_STATUS_BUSY, &cp->type,
4337 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004338 goto failed;
4339 }
4340
4341 uuid_count = __le16_to_cpu(cp->uuid_count);
4342 if (uuid_count > max_uuid_count) {
4343 BT_ERR("service_discovery: too big uuid_count value %u",
4344 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004345 err = mgmt_cmd_complete(sk, hdev->id,
4346 MGMT_OP_START_SERVICE_DISCOVERY,
4347 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4348 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004349 goto failed;
4350 }
4351
4352 expected_len = sizeof(*cp) + uuid_count * 16;
4353 if (expected_len != len) {
4354 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4355 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004356 err = mgmt_cmd_complete(sk, hdev->id,
4357 MGMT_OP_START_SERVICE_DISCOVERY,
4358 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4359 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004360 goto failed;
4361 }
4362
4363 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004364 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004365 if (!cmd) {
4366 err = -ENOMEM;
4367 goto failed;
4368 }
4369
Johan Hedberg2922a942014-12-05 13:36:06 +02004370 cmd->cmd_complete = service_discovery_cmd_complete;
4371
Marcel Holtmann22078802014-12-05 11:45:22 +01004372 /* Clear the discovery filter first to free any previously
4373 * allocated memory for the UUID list.
4374 */
4375 hci_discovery_filter_clear(hdev);
4376
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004377 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004378 hdev->discovery.type = cp->type;
4379 hdev->discovery.rssi = cp->rssi;
4380 hdev->discovery.uuid_count = uuid_count;
4381
4382 if (uuid_count > 0) {
4383 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4384 GFP_KERNEL);
4385 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004386 err = mgmt_cmd_complete(sk, hdev->id,
4387 MGMT_OP_START_SERVICE_DISCOVERY,
4388 MGMT_STATUS_FAILED,
4389 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004390 mgmt_pending_remove(cmd);
4391 goto failed;
4392 }
4393 }
4394
4395 hci_req_init(&req, hdev);
4396
4397 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004398 err = mgmt_cmd_complete(sk, hdev->id,
4399 MGMT_OP_START_SERVICE_DISCOVERY,
4400 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004401 mgmt_pending_remove(cmd);
4402 goto failed;
4403 }
4404
4405 err = hci_req_run(&req, start_discovery_complete);
4406 if (err < 0) {
4407 mgmt_pending_remove(cmd);
4408 goto failed;
4409 }
4410
4411 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4412
4413failed:
4414 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004415 return err;
4416}
4417
Marcel Holtmann1904a852015-01-11 13:50:44 -08004418static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004419{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004420 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004421
Andre Guedes0e05bba2013-04-30 15:29:33 -03004422 BT_DBG("status %d", status);
4423
4424 hci_dev_lock(hdev);
4425
Johan Hedberg333ae952015-03-17 13:48:47 +02004426 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004427 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004428 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004429 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004430 }
4431
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004432 if (!status)
4433 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004434
Andre Guedes0e05bba2013-04-30 15:29:33 -03004435 hci_dev_unlock(hdev);
4436}
4437
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004438static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004439 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004440{
Johan Hedbergd9306502012-02-20 23:25:18 +02004441 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004442 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004443 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004444 int err;
4445
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004446 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004447
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004448 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004449
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004450 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004451 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4452 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4453 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004454 goto unlock;
4455 }
4456
4457 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004458 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4459 MGMT_STATUS_INVALID_PARAMS,
4460 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004461 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004462 }
4463
Johan Hedberg2922a942014-12-05 13:36:06 +02004464 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004465 if (!cmd) {
4466 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004467 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004468 }
4469
Johan Hedberg2922a942014-12-05 13:36:06 +02004470 cmd->cmd_complete = generic_cmd_complete;
4471
Andre Guedes0e05bba2013-04-30 15:29:33 -03004472 hci_req_init(&req, hdev);
4473
Johan Hedberg21a60d32014-06-10 14:05:58 +03004474 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004475
Johan Hedberg21a60d32014-06-10 14:05:58 +03004476 err = hci_req_run(&req, stop_discovery_complete);
4477 if (!err) {
4478 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004479 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004480 }
4481
Johan Hedberg21a60d32014-06-10 14:05:58 +03004482 mgmt_pending_remove(cmd);
4483
4484 /* If no HCI commands were sent we're done */
4485 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004486 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4487 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004488 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4489 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004490
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004491unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004492 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004493 return err;
4494}
4495
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004496static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004497 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004498{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004499 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004500 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004501 int err;
4502
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004503 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004504
Johan Hedberg561aafb2012-01-04 13:31:59 +02004505 hci_dev_lock(hdev);
4506
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004507 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004508 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4509 MGMT_STATUS_FAILED, &cp->addr,
4510 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004511 goto failed;
4512 }
4513
Johan Hedberga198e7b2012-02-17 14:27:06 +02004514 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004515 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004516 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4517 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4518 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004519 goto failed;
4520 }
4521
4522 if (cp->name_known) {
4523 e->name_state = NAME_KNOWN;
4524 list_del(&e->list);
4525 } else {
4526 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004527 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004528 }
4529
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004530 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4531 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004532
4533failed:
4534 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004535 return err;
4536}
4537
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004538static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004539 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004540{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004541 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004542 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004543 int err;
4544
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004545 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004546
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004547 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004548 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4549 MGMT_STATUS_INVALID_PARAMS,
4550 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004551
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004552 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004553
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004554 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4555 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004556 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004557 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004558 goto done;
4559 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004560
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004561 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4562 sk);
4563 status = MGMT_STATUS_SUCCESS;
4564
4565done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004566 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4567 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004568
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004569 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004570
4571 return err;
4572}
4573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004574static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004575 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004576{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004577 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004578 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004579 int err;
4580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004581 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004582
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004583 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004584 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4585 MGMT_STATUS_INVALID_PARAMS,
4586 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004587
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004588 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004589
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004590 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4591 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004592 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004593 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004594 goto done;
4595 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004596
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004597 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4598 sk);
4599 status = MGMT_STATUS_SUCCESS;
4600
4601done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004602 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4603 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004604
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004605 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004606
4607 return err;
4608}
4609
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004610static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4611 u16 len)
4612{
4613 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004614 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004615 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004616 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004617
4618 BT_DBG("%s", hdev->name);
4619
Szymon Jancc72d4b82012-03-16 16:02:57 +01004620 source = __le16_to_cpu(cp->source);
4621
4622 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004623 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4624 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004625
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004626 hci_dev_lock(hdev);
4627
Szymon Jancc72d4b82012-03-16 16:02:57 +01004628 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004629 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4630 hdev->devid_product = __le16_to_cpu(cp->product);
4631 hdev->devid_version = __le16_to_cpu(cp->version);
4632
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004633 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4634 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004635
Johan Hedberg890ea892013-03-15 17:06:52 -05004636 hci_req_init(&req, hdev);
4637 update_eir(&req);
4638 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004639
4640 hci_dev_unlock(hdev);
4641
4642 return err;
4643}
4644
Arman Uguray24b4f382015-03-23 15:57:12 -07004645static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4646 u16 opcode)
4647{
4648 BT_DBG("status %d", status);
4649}
4650
Marcel Holtmann1904a852015-01-11 13:50:44 -08004651static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4652 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004653{
4654 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004655 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004656
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304657 hci_dev_lock(hdev);
4658
Johan Hedberg4375f102013-09-25 13:26:10 +03004659 if (status) {
4660 u8 mgmt_err = mgmt_status(status);
4661
4662 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4663 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304664 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004665 }
4666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004667 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004668 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004669 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004670 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004671
Johan Hedberg4375f102013-09-25 13:26:10 +03004672 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4673 &match);
4674
4675 new_settings(hdev, match.sk);
4676
4677 if (match.sk)
4678 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304679
Arman Uguray24b4f382015-03-23 15:57:12 -07004680 /* If "Set Advertising" was just disabled and instance advertising was
4681 * set up earlier, then enable the advertising instance.
4682 */
4683 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4684 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4685 goto unlock;
4686
4687 hci_req_init(&req, hdev);
4688
4689 update_adv_data(&req);
4690 enable_advertising(&req);
4691
4692 if (hci_req_run(&req, enable_advertising_instance) < 0)
4693 BT_ERR("Failed to re-configure advertising");
4694
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304695unlock:
4696 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004697}
4698
Marcel Holtmann21b51872013-10-10 09:47:53 -07004699static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4700 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004701{
4702 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004703 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004704 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004705 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004706 int err;
4707
4708 BT_DBG("request for %s", hdev->name);
4709
Johan Hedberge6fe7982013-10-02 15:45:22 +03004710 status = mgmt_le_support(hdev);
4711 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004712 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4713 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004714
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004715 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004716 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4717 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004718
4719 hci_dev_lock(hdev);
4720
4721 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004722
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004723 /* The following conditions are ones which mean that we should
4724 * not do any HCI communication but directly send a mgmt
4725 * response to user space (after toggling the flag if
4726 * necessary).
4727 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004728 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004729 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4730 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004731 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004732 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004733 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004734 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004735
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004736 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004737 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004738 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004739 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004740 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004741 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004742 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004743 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004744 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004745 }
4746
4747 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4748 if (err < 0)
4749 goto unlock;
4750
4751 if (changed)
4752 err = new_settings(hdev, sk);
4753
4754 goto unlock;
4755 }
4756
Johan Hedberg333ae952015-03-17 13:48:47 +02004757 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4758 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004759 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4760 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004761 goto unlock;
4762 }
4763
4764 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4765 if (!cmd) {
4766 err = -ENOMEM;
4767 goto unlock;
4768 }
4769
4770 hci_req_init(&req, hdev);
4771
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004772 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004773 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004774 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004775 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004776
Arman Uguray24b4f382015-03-23 15:57:12 -07004777 if (val) {
4778 /* Switch to instance "0" for the Set Advertising setting. */
4779 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004780 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004781 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004782 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004783 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004784 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004785
4786 err = hci_req_run(&req, set_advertising_complete);
4787 if (err < 0)
4788 mgmt_pending_remove(cmd);
4789
4790unlock:
4791 hci_dev_unlock(hdev);
4792 return err;
4793}
4794
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004795static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4796 void *data, u16 len)
4797{
4798 struct mgmt_cp_set_static_address *cp = data;
4799 int err;
4800
4801 BT_DBG("%s", hdev->name);
4802
Marcel Holtmann62af4442013-10-02 22:10:32 -07004803 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004804 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4805 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004806
4807 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004808 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4809 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004810
4811 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4812 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004813 return mgmt_cmd_status(sk, hdev->id,
4814 MGMT_OP_SET_STATIC_ADDRESS,
4815 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004816
4817 /* Two most significant bits shall be set */
4818 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004819 return mgmt_cmd_status(sk, hdev->id,
4820 MGMT_OP_SET_STATIC_ADDRESS,
4821 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004822 }
4823
4824 hci_dev_lock(hdev);
4825
4826 bacpy(&hdev->static_addr, &cp->bdaddr);
4827
Marcel Holtmann93690c22015-03-06 10:11:21 -08004828 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4829 if (err < 0)
4830 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004831
Marcel Holtmann93690c22015-03-06 10:11:21 -08004832 err = new_settings(hdev, sk);
4833
4834unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004835 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004836 return err;
4837}
4838
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004839static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4840 void *data, u16 len)
4841{
4842 struct mgmt_cp_set_scan_params *cp = data;
4843 __u16 interval, window;
4844 int err;
4845
4846 BT_DBG("%s", hdev->name);
4847
4848 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004849 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4850 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004851
4852 interval = __le16_to_cpu(cp->interval);
4853
4854 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004855 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4856 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004857
4858 window = __le16_to_cpu(cp->window);
4859
4860 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004861 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4862 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004863
Marcel Holtmann899e1072013-10-14 09:55:32 -07004864 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004865 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4866 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004867
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004868 hci_dev_lock(hdev);
4869
4870 hdev->le_scan_interval = interval;
4871 hdev->le_scan_window = window;
4872
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004873 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4874 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004875
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004876 /* If background scan is running, restart it so new parameters are
4877 * loaded.
4878 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004879 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004880 hdev->discovery.state == DISCOVERY_STOPPED) {
4881 struct hci_request req;
4882
4883 hci_req_init(&req, hdev);
4884
4885 hci_req_add_le_scan_disable(&req);
4886 hci_req_add_le_passive_scan(&req);
4887
4888 hci_req_run(&req, NULL);
4889 }
4890
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004891 hci_dev_unlock(hdev);
4892
4893 return err;
4894}
4895
Marcel Holtmann1904a852015-01-11 13:50:44 -08004896static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4897 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004898{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004899 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004900
4901 BT_DBG("status 0x%02x", status);
4902
4903 hci_dev_lock(hdev);
4904
Johan Hedberg333ae952015-03-17 13:48:47 +02004905 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004906 if (!cmd)
4907 goto unlock;
4908
4909 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004910 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4911 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004912 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004913 struct mgmt_mode *cp = cmd->param;
4914
4915 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004916 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004917 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004918 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004919
Johan Hedberg33e38b32013-03-15 17:07:05 -05004920 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4921 new_settings(hdev, cmd->sk);
4922 }
4923
4924 mgmt_pending_remove(cmd);
4925
4926unlock:
4927 hci_dev_unlock(hdev);
4928}
4929
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004930static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004931 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004932{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004933 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004934 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004935 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004936 int err;
4937
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004938 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004939
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004940 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004941 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004942 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4943 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004944
Johan Hedberga7e80f22013-01-09 16:05:19 +02004945 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004946 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4947 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004948
Antti Julkuf6422ec2011-06-22 13:11:56 +03004949 hci_dev_lock(hdev);
4950
Johan Hedberg333ae952015-03-17 13:48:47 +02004951 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004952 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4953 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004954 goto unlock;
4955 }
4956
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004957 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004958 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4959 hdev);
4960 goto unlock;
4961 }
4962
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004963 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004964 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004965 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4966 hdev);
4967 new_settings(hdev, sk);
4968 goto unlock;
4969 }
4970
Johan Hedberg33e38b32013-03-15 17:07:05 -05004971 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4972 data, len);
4973 if (!cmd) {
4974 err = -ENOMEM;
4975 goto unlock;
4976 }
4977
4978 hci_req_init(&req, hdev);
4979
Johan Hedberg406d7802013-03-15 17:07:09 -05004980 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004981
4982 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004983 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004984 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4985 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004986 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004987 }
4988
Johan Hedberg33e38b32013-03-15 17:07:05 -05004989unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004990 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004991
Antti Julkuf6422ec2011-06-22 13:11:56 +03004992 return err;
4993}
4994
Marcel Holtmann1904a852015-01-11 13:50:44 -08004995static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004996{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004997 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004998
4999 BT_DBG("status 0x%02x", status);
5000
5001 hci_dev_lock(hdev);
5002
Johan Hedberg333ae952015-03-17 13:48:47 +02005003 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005004 if (!cmd)
5005 goto unlock;
5006
5007 if (status) {
5008 u8 mgmt_err = mgmt_status(status);
5009
5010 /* We need to restore the flag if related HCI commands
5011 * failed.
5012 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005013 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005014
Johan Hedberga69e8372015-03-06 21:08:53 +02005015 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005016 } else {
5017 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
5018 new_settings(hdev, cmd->sk);
5019 }
5020
5021 mgmt_pending_remove(cmd);
5022
5023unlock:
5024 hci_dev_unlock(hdev);
5025}
5026
5027static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
5028{
5029 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005030 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005031 struct hci_request req;
5032 int err;
5033
5034 BT_DBG("request for %s", hdev->name);
5035
5036 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005037 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5038 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005039
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005040 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005041 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5042 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005043
5044 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005045 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5046 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005047
5048 hci_dev_lock(hdev);
5049
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005050 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005051 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5052 goto unlock;
5053 }
5054
5055 if (!hdev_is_powered(hdev)) {
5056 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005057 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5058 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5059 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5060 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5061 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005062 }
5063
Marcel Holtmannce05d602015-03-13 02:11:03 -07005064 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005065
5066 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5067 if (err < 0)
5068 goto unlock;
5069
5070 err = new_settings(hdev, sk);
5071 goto unlock;
5072 }
5073
5074 /* Reject disabling when powered on */
5075 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005076 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5077 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005078 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005079 } else {
5080 /* When configuring a dual-mode controller to operate
5081 * with LE only and using a static address, then switching
5082 * BR/EDR back on is not allowed.
5083 *
5084 * Dual-mode controllers shall operate with the public
5085 * address as its identity address for BR/EDR and LE. So
5086 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005087 *
5088 * The same restrictions applies when secure connections
5089 * has been enabled. For BR/EDR this is a controller feature
5090 * while for LE it is a host stack feature. This means that
5091 * switching BR/EDR back on when secure connections has been
5092 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005093 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005094 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005095 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005096 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005097 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5098 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005099 goto unlock;
5100 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005101 }
5102
Johan Hedberg333ae952015-03-17 13:48:47 +02005103 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005104 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5105 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005106 goto unlock;
5107 }
5108
5109 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5110 if (!cmd) {
5111 err = -ENOMEM;
5112 goto unlock;
5113 }
5114
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005115 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005116 * generates the correct flags.
5117 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005118 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005119
5120 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005121
Johan Hedberg432df052014-08-01 11:13:31 +03005122 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005123 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005124
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005125 /* Since only the advertising data flags will change, there
5126 * is no need to update the scan response data.
5127 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005128 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005129
Johan Hedberg0663ca22013-10-02 13:43:14 +03005130 err = hci_req_run(&req, set_bredr_complete);
5131 if (err < 0)
5132 mgmt_pending_remove(cmd);
5133
5134unlock:
5135 hci_dev_unlock(hdev);
5136 return err;
5137}
5138
Johan Hedberga1443f52015-01-23 15:42:46 +02005139static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5140{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005141 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005142 struct mgmt_mode *cp;
5143
5144 BT_DBG("%s status %u", hdev->name, status);
5145
5146 hci_dev_lock(hdev);
5147
Johan Hedberg333ae952015-03-17 13:48:47 +02005148 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005149 if (!cmd)
5150 goto unlock;
5151
5152 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005153 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5154 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005155 goto remove;
5156 }
5157
5158 cp = cmd->param;
5159
5160 switch (cp->val) {
5161 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005162 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5163 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005164 break;
5165 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005166 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005167 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005168 break;
5169 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005170 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5171 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005172 break;
5173 }
5174
5175 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5176 new_settings(hdev, cmd->sk);
5177
5178remove:
5179 mgmt_pending_remove(cmd);
5180unlock:
5181 hci_dev_unlock(hdev);
5182}
5183
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005184static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5185 void *data, u16 len)
5186{
5187 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005188 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005189 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005190 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005191 int err;
5192
5193 BT_DBG("request for %s", hdev->name);
5194
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005195 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005196 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005197 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5198 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005199
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005200 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005201 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005202 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005203 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5204 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005205
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005206 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005207 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005208 MGMT_STATUS_INVALID_PARAMS);
5209
5210 hci_dev_lock(hdev);
5211
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005212 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005213 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005214 bool changed;
5215
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005216 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005217 changed = !hci_dev_test_and_set_flag(hdev,
5218 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005219 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005220 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005221 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005222 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005223 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005224 changed = hci_dev_test_and_clear_flag(hdev,
5225 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005226 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005227 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005228
5229 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5230 if (err < 0)
5231 goto failed;
5232
5233 if (changed)
5234 err = new_settings(hdev, sk);
5235
5236 goto failed;
5237 }
5238
Johan Hedberg333ae952015-03-17 13:48:47 +02005239 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005240 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5241 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005242 goto failed;
5243 }
5244
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005245 val = !!cp->val;
5246
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005247 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5248 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005249 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5250 goto failed;
5251 }
5252
5253 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5254 if (!cmd) {
5255 err = -ENOMEM;
5256 goto failed;
5257 }
5258
Johan Hedberga1443f52015-01-23 15:42:46 +02005259 hci_req_init(&req, hdev);
5260 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5261 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005262 if (err < 0) {
5263 mgmt_pending_remove(cmd);
5264 goto failed;
5265 }
5266
5267failed:
5268 hci_dev_unlock(hdev);
5269 return err;
5270}
5271
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005272static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5273 void *data, u16 len)
5274{
5275 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005276 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005277 int err;
5278
5279 BT_DBG("request for %s", hdev->name);
5280
Johan Hedbergb97109792014-06-24 14:00:28 +03005281 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005282 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5283 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005284
5285 hci_dev_lock(hdev);
5286
5287 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005288 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005289 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005290 changed = hci_dev_test_and_clear_flag(hdev,
5291 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005292
Johan Hedbergb97109792014-06-24 14:00:28 +03005293 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005294 use_changed = !hci_dev_test_and_set_flag(hdev,
5295 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005296 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005297 use_changed = hci_dev_test_and_clear_flag(hdev,
5298 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005299
5300 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005301 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005302 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5303 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5304 sizeof(mode), &mode);
5305 }
5306
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005307 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5308 if (err < 0)
5309 goto unlock;
5310
5311 if (changed)
5312 err = new_settings(hdev, sk);
5313
5314unlock:
5315 hci_dev_unlock(hdev);
5316 return err;
5317}
5318
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005319static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5320 u16 len)
5321{
5322 struct mgmt_cp_set_privacy *cp = cp_data;
5323 bool changed;
5324 int err;
5325
5326 BT_DBG("request for %s", hdev->name);
5327
5328 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005329 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5330 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005331
5332 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005333 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5334 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005335
5336 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005337 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5338 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005339
5340 hci_dev_lock(hdev);
5341
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005342 /* If user space supports this command it is also expected to
5343 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5344 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005345 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005346
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005347 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005348 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005349 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005350 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005351 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005352 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005353 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005354 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005355 }
5356
5357 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5358 if (err < 0)
5359 goto unlock;
5360
5361 if (changed)
5362 err = new_settings(hdev, sk);
5363
5364unlock:
5365 hci_dev_unlock(hdev);
5366 return err;
5367}
5368
Johan Hedberg41edf162014-02-18 10:19:35 +02005369static bool irk_is_valid(struct mgmt_irk_info *irk)
5370{
5371 switch (irk->addr.type) {
5372 case BDADDR_LE_PUBLIC:
5373 return true;
5374
5375 case BDADDR_LE_RANDOM:
5376 /* Two most significant bits shall be set */
5377 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5378 return false;
5379 return true;
5380 }
5381
5382 return false;
5383}
5384
5385static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5386 u16 len)
5387{
5388 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005389 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5390 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005391 u16 irk_count, expected_len;
5392 int i, err;
5393
5394 BT_DBG("request for %s", hdev->name);
5395
5396 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005397 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5398 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005399
5400 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005401 if (irk_count > max_irk_count) {
5402 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005403 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5404 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005405 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005406
5407 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5408 if (expected_len != len) {
5409 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005410 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005411 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5412 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005413 }
5414
5415 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5416
5417 for (i = 0; i < irk_count; i++) {
5418 struct mgmt_irk_info *key = &cp->irks[i];
5419
5420 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005421 return mgmt_cmd_status(sk, hdev->id,
5422 MGMT_OP_LOAD_IRKS,
5423 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005424 }
5425
5426 hci_dev_lock(hdev);
5427
5428 hci_smp_irks_clear(hdev);
5429
5430 for (i = 0; i < irk_count; i++) {
5431 struct mgmt_irk_info *irk = &cp->irks[i];
5432 u8 addr_type;
5433
5434 if (irk->addr.type == BDADDR_LE_PUBLIC)
5435 addr_type = ADDR_LE_DEV_PUBLIC;
5436 else
5437 addr_type = ADDR_LE_DEV_RANDOM;
5438
5439 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5440 BDADDR_ANY);
5441 }
5442
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005443 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005444
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005445 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005446
5447 hci_dev_unlock(hdev);
5448
5449 return err;
5450}
5451
Johan Hedberg3f706b72013-01-20 14:27:16 +02005452static bool ltk_is_valid(struct mgmt_ltk_info *key)
5453{
5454 if (key->master != 0x00 && key->master != 0x01)
5455 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005456
5457 switch (key->addr.type) {
5458 case BDADDR_LE_PUBLIC:
5459 return true;
5460
5461 case BDADDR_LE_RANDOM:
5462 /* Two most significant bits shall be set */
5463 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5464 return false;
5465 return true;
5466 }
5467
5468 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005469}
5470
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005471static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005472 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005473{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005474 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005475 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5476 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005477 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005478 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005479
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005480 BT_DBG("request for %s", hdev->name);
5481
5482 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005483 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5484 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005485
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005486 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005487 if (key_count > max_key_count) {
5488 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005489 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5490 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005491 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005492
5493 expected_len = sizeof(*cp) + key_count *
5494 sizeof(struct mgmt_ltk_info);
5495 if (expected_len != len) {
5496 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005497 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005498 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5499 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005500 }
5501
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005502 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005503
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005504 for (i = 0; i < key_count; i++) {
5505 struct mgmt_ltk_info *key = &cp->keys[i];
5506
Johan Hedberg3f706b72013-01-20 14:27:16 +02005507 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005508 return mgmt_cmd_status(sk, hdev->id,
5509 MGMT_OP_LOAD_LONG_TERM_KEYS,
5510 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005511 }
5512
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005513 hci_dev_lock(hdev);
5514
5515 hci_smp_ltks_clear(hdev);
5516
5517 for (i = 0; i < key_count; i++) {
5518 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005519 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005520
5521 if (key->addr.type == BDADDR_LE_PUBLIC)
5522 addr_type = ADDR_LE_DEV_PUBLIC;
5523 else
5524 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005525
Johan Hedberg61b43352014-05-29 19:36:53 +03005526 switch (key->type) {
5527 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005528 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005529 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005530 break;
5531 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005532 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005533 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005534 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005535 case MGMT_LTK_P256_UNAUTH:
5536 authenticated = 0x00;
5537 type = SMP_LTK_P256;
5538 break;
5539 case MGMT_LTK_P256_AUTH:
5540 authenticated = 0x01;
5541 type = SMP_LTK_P256;
5542 break;
5543 case MGMT_LTK_P256_DEBUG:
5544 authenticated = 0x00;
5545 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005546 default:
5547 continue;
5548 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005549
Johan Hedberg35d70272014-02-19 14:57:47 +02005550 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005551 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005552 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005553 }
5554
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005555 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005556 NULL, 0);
5557
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005558 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005559
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005560 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005561}
5562
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005563static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005564{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005565 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005566 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005567 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005568
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005569 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005570
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005571 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005572 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005573 rp.tx_power = conn->tx_power;
5574 rp.max_tx_power = conn->max_tx_power;
5575 } else {
5576 rp.rssi = HCI_RSSI_INVALID;
5577 rp.tx_power = HCI_TX_POWER_INVALID;
5578 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005579 }
5580
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005581 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5582 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005583
5584 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005585 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005586
5587 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005588}
5589
Marcel Holtmann1904a852015-01-11 13:50:44 -08005590static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5591 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005592{
5593 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005594 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005595 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005596 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005597 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005598
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005599 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005600
5601 hci_dev_lock(hdev);
5602
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005603 /* Commands sent in request are either Read RSSI or Read Transmit Power
5604 * Level so we check which one was last sent to retrieve connection
5605 * handle. Both commands have handle as first parameter so it's safe to
5606 * cast data on the same command struct.
5607 *
5608 * First command sent is always Read RSSI and we fail only if it fails.
5609 * In other case we simply override error to indicate success as we
5610 * already remembered if TX power value is actually valid.
5611 */
5612 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5613 if (!cp) {
5614 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005615 status = MGMT_STATUS_SUCCESS;
5616 } else {
5617 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005618 }
5619
5620 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005621 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005622 goto unlock;
5623 }
5624
5625 handle = __le16_to_cpu(cp->handle);
5626 conn = hci_conn_hash_lookup_handle(hdev, handle);
5627 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005628 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005629 goto unlock;
5630 }
5631
Johan Hedberg333ae952015-03-17 13:48:47 +02005632 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005633 if (!cmd)
5634 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005635
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005636 cmd->cmd_complete(cmd, status);
5637 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005638
5639unlock:
5640 hci_dev_unlock(hdev);
5641}
5642
5643static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5644 u16 len)
5645{
5646 struct mgmt_cp_get_conn_info *cp = data;
5647 struct mgmt_rp_get_conn_info rp;
5648 struct hci_conn *conn;
5649 unsigned long conn_info_age;
5650 int err = 0;
5651
5652 BT_DBG("%s", hdev->name);
5653
5654 memset(&rp, 0, sizeof(rp));
5655 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5656 rp.addr.type = cp->addr.type;
5657
5658 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005659 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5660 MGMT_STATUS_INVALID_PARAMS,
5661 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005662
5663 hci_dev_lock(hdev);
5664
5665 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005666 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5667 MGMT_STATUS_NOT_POWERED, &rp,
5668 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005669 goto unlock;
5670 }
5671
5672 if (cp->addr.type == BDADDR_BREDR)
5673 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5674 &cp->addr.bdaddr);
5675 else
5676 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5677
5678 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005679 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5680 MGMT_STATUS_NOT_CONNECTED, &rp,
5681 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005682 goto unlock;
5683 }
5684
Johan Hedberg333ae952015-03-17 13:48:47 +02005685 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005686 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5687 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005688 goto unlock;
5689 }
5690
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005691 /* To avoid client trying to guess when to poll again for information we
5692 * calculate conn info age as random value between min/max set in hdev.
5693 */
5694 conn_info_age = hdev->conn_info_min_age +
5695 prandom_u32_max(hdev->conn_info_max_age -
5696 hdev->conn_info_min_age);
5697
5698 /* Query controller to refresh cached values if they are too old or were
5699 * never read.
5700 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005701 if (time_after(jiffies, conn->conn_info_timestamp +
5702 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005703 !conn->conn_info_timestamp) {
5704 struct hci_request req;
5705 struct hci_cp_read_tx_power req_txp_cp;
5706 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005707 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005708
5709 hci_req_init(&req, hdev);
5710 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5711 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5712 &req_rssi_cp);
5713
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005714 /* For LE links TX power does not change thus we don't need to
5715 * query for it once value is known.
5716 */
5717 if (!bdaddr_type_is_le(cp->addr.type) ||
5718 conn->tx_power == HCI_TX_POWER_INVALID) {
5719 req_txp_cp.handle = cpu_to_le16(conn->handle);
5720 req_txp_cp.type = 0x00;
5721 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5722 sizeof(req_txp_cp), &req_txp_cp);
5723 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005724
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005725 /* Max TX power needs to be read only once per connection */
5726 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5727 req_txp_cp.handle = cpu_to_le16(conn->handle);
5728 req_txp_cp.type = 0x01;
5729 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5730 sizeof(req_txp_cp), &req_txp_cp);
5731 }
5732
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005733 err = hci_req_run(&req, conn_info_refresh_complete);
5734 if (err < 0)
5735 goto unlock;
5736
5737 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5738 data, len);
5739 if (!cmd) {
5740 err = -ENOMEM;
5741 goto unlock;
5742 }
5743
5744 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005745 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005746 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005747
5748 conn->conn_info_timestamp = jiffies;
5749 } else {
5750 /* Cache is valid, just reply with values cached in hci_conn */
5751 rp.rssi = conn->rssi;
5752 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005753 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005754
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005755 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5756 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005757 }
5758
5759unlock:
5760 hci_dev_unlock(hdev);
5761 return err;
5762}
5763
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005764static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005765{
5766 struct hci_conn *conn = cmd->user_data;
5767 struct mgmt_rp_get_clock_info rp;
5768 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005769 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005770
5771 memset(&rp, 0, sizeof(rp));
5772 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5773
5774 if (status)
5775 goto complete;
5776
5777 hdev = hci_dev_get(cmd->index);
5778 if (hdev) {
5779 rp.local_clock = cpu_to_le32(hdev->clock);
5780 hci_dev_put(hdev);
5781 }
5782
5783 if (conn) {
5784 rp.piconet_clock = cpu_to_le32(conn->clock);
5785 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5786 }
5787
5788complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005789 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5790 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005791
5792 if (conn) {
5793 hci_conn_drop(conn);
5794 hci_conn_put(conn);
5795 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005796
5797 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005798}
5799
Marcel Holtmann1904a852015-01-11 13:50:44 -08005800static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005801{
Johan Hedberg95868422014-06-28 17:54:07 +03005802 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005803 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005804 struct hci_conn *conn;
5805
5806 BT_DBG("%s status %u", hdev->name, status);
5807
5808 hci_dev_lock(hdev);
5809
5810 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5811 if (!hci_cp)
5812 goto unlock;
5813
5814 if (hci_cp->which) {
5815 u16 handle = __le16_to_cpu(hci_cp->handle);
5816 conn = hci_conn_hash_lookup_handle(hdev, handle);
5817 } else {
5818 conn = NULL;
5819 }
5820
Johan Hedberg333ae952015-03-17 13:48:47 +02005821 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005822 if (!cmd)
5823 goto unlock;
5824
Johan Hedberg69487372014-12-05 13:36:07 +02005825 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005826 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005827
5828unlock:
5829 hci_dev_unlock(hdev);
5830}
5831
5832static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5833 u16 len)
5834{
5835 struct mgmt_cp_get_clock_info *cp = data;
5836 struct mgmt_rp_get_clock_info rp;
5837 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005838 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005839 struct hci_request req;
5840 struct hci_conn *conn;
5841 int err;
5842
5843 BT_DBG("%s", hdev->name);
5844
5845 memset(&rp, 0, sizeof(rp));
5846 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5847 rp.addr.type = cp->addr.type;
5848
5849 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005850 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5851 MGMT_STATUS_INVALID_PARAMS,
5852 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005853
5854 hci_dev_lock(hdev);
5855
5856 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005857 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5858 MGMT_STATUS_NOT_POWERED, &rp,
5859 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005860 goto unlock;
5861 }
5862
5863 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5864 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5865 &cp->addr.bdaddr);
5866 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005867 err = mgmt_cmd_complete(sk, hdev->id,
5868 MGMT_OP_GET_CLOCK_INFO,
5869 MGMT_STATUS_NOT_CONNECTED,
5870 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005871 goto unlock;
5872 }
5873 } else {
5874 conn = NULL;
5875 }
5876
5877 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5878 if (!cmd) {
5879 err = -ENOMEM;
5880 goto unlock;
5881 }
5882
Johan Hedberg69487372014-12-05 13:36:07 +02005883 cmd->cmd_complete = clock_info_cmd_complete;
5884
Johan Hedberg95868422014-06-28 17:54:07 +03005885 hci_req_init(&req, hdev);
5886
5887 memset(&hci_cp, 0, sizeof(hci_cp));
5888 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5889
5890 if (conn) {
5891 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005892 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005893
5894 hci_cp.handle = cpu_to_le16(conn->handle);
5895 hci_cp.which = 0x01; /* Piconet clock */
5896 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5897 }
5898
5899 err = hci_req_run(&req, get_clock_info_complete);
5900 if (err < 0)
5901 mgmt_pending_remove(cmd);
5902
5903unlock:
5904 hci_dev_unlock(hdev);
5905 return err;
5906}
5907
Johan Hedberg5a154e62014-12-19 22:26:02 +02005908static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5909{
5910 struct hci_conn *conn;
5911
5912 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5913 if (!conn)
5914 return false;
5915
5916 if (conn->dst_type != type)
5917 return false;
5918
5919 if (conn->state != BT_CONNECTED)
5920 return false;
5921
5922 return true;
5923}
5924
5925/* This function requires the caller holds hdev->lock */
5926static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5927 u8 addr_type, u8 auto_connect)
5928{
5929 struct hci_dev *hdev = req->hdev;
5930 struct hci_conn_params *params;
5931
5932 params = hci_conn_params_add(hdev, addr, addr_type);
5933 if (!params)
5934 return -EIO;
5935
5936 if (params->auto_connect == auto_connect)
5937 return 0;
5938
5939 list_del_init(&params->action);
5940
5941 switch (auto_connect) {
5942 case HCI_AUTO_CONN_DISABLED:
5943 case HCI_AUTO_CONN_LINK_LOSS:
5944 __hci_update_background_scan(req);
5945 break;
5946 case HCI_AUTO_CONN_REPORT:
5947 list_add(&params->action, &hdev->pend_le_reports);
5948 __hci_update_background_scan(req);
5949 break;
5950 case HCI_AUTO_CONN_DIRECT:
5951 case HCI_AUTO_CONN_ALWAYS:
5952 if (!is_connected(hdev, addr, addr_type)) {
5953 list_add(&params->action, &hdev->pend_le_conns);
5954 __hci_update_background_scan(req);
5955 }
5956 break;
5957 }
5958
5959 params->auto_connect = auto_connect;
5960
5961 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5962 auto_connect);
5963
5964 return 0;
5965}
5966
Marcel Holtmann8afef092014-06-29 22:28:34 +02005967static void device_added(struct sock *sk, struct hci_dev *hdev,
5968 bdaddr_t *bdaddr, u8 type, u8 action)
5969{
5970 struct mgmt_ev_device_added ev;
5971
5972 bacpy(&ev.addr.bdaddr, bdaddr);
5973 ev.addr.type = type;
5974 ev.action = action;
5975
5976 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5977}
5978
Marcel Holtmann1904a852015-01-11 13:50:44 -08005979static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005980{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005981 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005982
5983 BT_DBG("status 0x%02x", status);
5984
5985 hci_dev_lock(hdev);
5986
Johan Hedberg333ae952015-03-17 13:48:47 +02005987 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005988 if (!cmd)
5989 goto unlock;
5990
5991 cmd->cmd_complete(cmd, mgmt_status(status));
5992 mgmt_pending_remove(cmd);
5993
5994unlock:
5995 hci_dev_unlock(hdev);
5996}
5997
Marcel Holtmann2faade52014-06-29 19:44:03 +02005998static int add_device(struct sock *sk, struct hci_dev *hdev,
5999 void *data, u16 len)
6000{
6001 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006002 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006003 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006004 u8 auto_conn, addr_type;
6005 int err;
6006
6007 BT_DBG("%s", hdev->name);
6008
Johan Hedberg66593582014-07-09 12:59:14 +03006009 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02006010 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006011 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6012 MGMT_STATUS_INVALID_PARAMS,
6013 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006014
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006015 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006016 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6017 MGMT_STATUS_INVALID_PARAMS,
6018 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006019
Johan Hedberg5a154e62014-12-19 22:26:02 +02006020 hci_req_init(&req, hdev);
6021
Marcel Holtmann2faade52014-06-29 19:44:03 +02006022 hci_dev_lock(hdev);
6023
Johan Hedberg5a154e62014-12-19 22:26:02 +02006024 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
6025 if (!cmd) {
6026 err = -ENOMEM;
6027 goto unlock;
6028 }
6029
6030 cmd->cmd_complete = addr_cmd_complete;
6031
Johan Hedberg66593582014-07-09 12:59:14 +03006032 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006033 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03006034 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006035 err = cmd->cmd_complete(cmd,
6036 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006037 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006038 goto unlock;
6039 }
6040
6041 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
6042 cp->addr.type);
6043 if (err)
6044 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03006045
Johan Hedberg5a154e62014-12-19 22:26:02 +02006046 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006047
Johan Hedberg66593582014-07-09 12:59:14 +03006048 goto added;
6049 }
6050
Marcel Holtmann2faade52014-06-29 19:44:03 +02006051 if (cp->addr.type == BDADDR_LE_PUBLIC)
6052 addr_type = ADDR_LE_DEV_PUBLIC;
6053 else
6054 addr_type = ADDR_LE_DEV_RANDOM;
6055
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006056 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006057 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006058 else if (cp->action == 0x01)
6059 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006060 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006061 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006062
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006063 /* If the connection parameters don't exist for this device,
6064 * they will be created and configured with defaults.
6065 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006066 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006067 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006068 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006069 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006070 goto unlock;
6071 }
6072
Johan Hedberg66593582014-07-09 12:59:14 +03006073added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006074 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6075
Johan Hedberg5a154e62014-12-19 22:26:02 +02006076 err = hci_req_run(&req, add_device_complete);
6077 if (err < 0) {
6078 /* ENODATA means no HCI commands were needed (e.g. if
6079 * the adapter is powered off).
6080 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006081 if (err == -ENODATA)
6082 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006083 mgmt_pending_remove(cmd);
6084 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006085
6086unlock:
6087 hci_dev_unlock(hdev);
6088 return err;
6089}
6090
Marcel Holtmann8afef092014-06-29 22:28:34 +02006091static void device_removed(struct sock *sk, struct hci_dev *hdev,
6092 bdaddr_t *bdaddr, u8 type)
6093{
6094 struct mgmt_ev_device_removed ev;
6095
6096 bacpy(&ev.addr.bdaddr, bdaddr);
6097 ev.addr.type = type;
6098
6099 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6100}
6101
Marcel Holtmann1904a852015-01-11 13:50:44 -08006102static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006103{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006104 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006105
6106 BT_DBG("status 0x%02x", status);
6107
6108 hci_dev_lock(hdev);
6109
Johan Hedberg333ae952015-03-17 13:48:47 +02006110 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006111 if (!cmd)
6112 goto unlock;
6113
6114 cmd->cmd_complete(cmd, mgmt_status(status));
6115 mgmt_pending_remove(cmd);
6116
6117unlock:
6118 hci_dev_unlock(hdev);
6119}
6120
Marcel Holtmann2faade52014-06-29 19:44:03 +02006121static int remove_device(struct sock *sk, struct hci_dev *hdev,
6122 void *data, u16 len)
6123{
6124 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006125 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006126 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006127 int err;
6128
6129 BT_DBG("%s", hdev->name);
6130
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006131 hci_req_init(&req, hdev);
6132
Marcel Holtmann2faade52014-06-29 19:44:03 +02006133 hci_dev_lock(hdev);
6134
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006135 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6136 if (!cmd) {
6137 err = -ENOMEM;
6138 goto unlock;
6139 }
6140
6141 cmd->cmd_complete = addr_cmd_complete;
6142
Marcel Holtmann2faade52014-06-29 19:44:03 +02006143 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006144 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006145 u8 addr_type;
6146
Johan Hedberg66593582014-07-09 12:59:14 +03006147 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006148 err = cmd->cmd_complete(cmd,
6149 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006150 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006151 goto unlock;
6152 }
6153
Johan Hedberg66593582014-07-09 12:59:14 +03006154 if (cp->addr.type == BDADDR_BREDR) {
6155 err = hci_bdaddr_list_del(&hdev->whitelist,
6156 &cp->addr.bdaddr,
6157 cp->addr.type);
6158 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006159 err = cmd->cmd_complete(cmd,
6160 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006161 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006162 goto unlock;
6163 }
6164
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006165 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006166
Johan Hedberg66593582014-07-09 12:59:14 +03006167 device_removed(sk, hdev, &cp->addr.bdaddr,
6168 cp->addr.type);
6169 goto complete;
6170 }
6171
Marcel Holtmann2faade52014-06-29 19:44:03 +02006172 if (cp->addr.type == BDADDR_LE_PUBLIC)
6173 addr_type = ADDR_LE_DEV_PUBLIC;
6174 else
6175 addr_type = ADDR_LE_DEV_RANDOM;
6176
Johan Hedbergc71593d2014-07-02 17:37:28 +03006177 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6178 addr_type);
6179 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006180 err = cmd->cmd_complete(cmd,
6181 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006182 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006183 goto unlock;
6184 }
6185
6186 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006187 err = cmd->cmd_complete(cmd,
6188 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006189 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006190 goto unlock;
6191 }
6192
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006193 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006194 list_del(&params->list);
6195 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006196 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006197
6198 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006199 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006200 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006201 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006202
Marcel Holtmann2faade52014-06-29 19:44:03 +02006203 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006204 err = cmd->cmd_complete(cmd,
6205 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006206 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006207 goto unlock;
6208 }
6209
Johan Hedberg66593582014-07-09 12:59:14 +03006210 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6211 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6212 list_del(&b->list);
6213 kfree(b);
6214 }
6215
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006216 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006217
Johan Hedberg19de0822014-07-06 13:06:51 +03006218 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6219 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6220 continue;
6221 device_removed(sk, hdev, &p->addr, p->addr_type);
6222 list_del(&p->action);
6223 list_del(&p->list);
6224 kfree(p);
6225 }
6226
6227 BT_DBG("All LE connection parameters were removed");
6228
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006229 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006230 }
6231
Johan Hedberg66593582014-07-09 12:59:14 +03006232complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006233 err = hci_req_run(&req, remove_device_complete);
6234 if (err < 0) {
6235 /* ENODATA means no HCI commands were needed (e.g. if
6236 * the adapter is powered off).
6237 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006238 if (err == -ENODATA)
6239 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006240 mgmt_pending_remove(cmd);
6241 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006242
6243unlock:
6244 hci_dev_unlock(hdev);
6245 return err;
6246}
6247
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006248static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6249 u16 len)
6250{
6251 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006252 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6253 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006254 u16 param_count, expected_len;
6255 int i;
6256
6257 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006258 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6259 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006260
6261 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006262 if (param_count > max_param_count) {
6263 BT_ERR("load_conn_param: too big param_count value %u",
6264 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006265 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6266 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006267 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006268
6269 expected_len = sizeof(*cp) + param_count *
6270 sizeof(struct mgmt_conn_param);
6271 if (expected_len != len) {
6272 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6273 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006274 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6275 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006276 }
6277
6278 BT_DBG("%s param_count %u", hdev->name, param_count);
6279
6280 hci_dev_lock(hdev);
6281
6282 hci_conn_params_clear_disabled(hdev);
6283
6284 for (i = 0; i < param_count; i++) {
6285 struct mgmt_conn_param *param = &cp->params[i];
6286 struct hci_conn_params *hci_param;
6287 u16 min, max, latency, timeout;
6288 u8 addr_type;
6289
6290 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6291 param->addr.type);
6292
6293 if (param->addr.type == BDADDR_LE_PUBLIC) {
6294 addr_type = ADDR_LE_DEV_PUBLIC;
6295 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6296 addr_type = ADDR_LE_DEV_RANDOM;
6297 } else {
6298 BT_ERR("Ignoring invalid connection parameters");
6299 continue;
6300 }
6301
6302 min = le16_to_cpu(param->min_interval);
6303 max = le16_to_cpu(param->max_interval);
6304 latency = le16_to_cpu(param->latency);
6305 timeout = le16_to_cpu(param->timeout);
6306
6307 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6308 min, max, latency, timeout);
6309
6310 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6311 BT_ERR("Ignoring invalid connection parameters");
6312 continue;
6313 }
6314
6315 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6316 addr_type);
6317 if (!hci_param) {
6318 BT_ERR("Failed to add connection parameters");
6319 continue;
6320 }
6321
6322 hci_param->conn_min_interval = min;
6323 hci_param->conn_max_interval = max;
6324 hci_param->conn_latency = latency;
6325 hci_param->supervision_timeout = timeout;
6326 }
6327
6328 hci_dev_unlock(hdev);
6329
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006330 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6331 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006332}
6333
Marcel Holtmanndbece372014-07-04 18:11:55 +02006334static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6335 void *data, u16 len)
6336{
6337 struct mgmt_cp_set_external_config *cp = data;
6338 bool changed;
6339 int err;
6340
6341 BT_DBG("%s", hdev->name);
6342
6343 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006344 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6345 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006346
6347 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006348 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6349 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006350
6351 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006352 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6353 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006354
6355 hci_dev_lock(hdev);
6356
6357 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006358 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006359 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006360 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006361
6362 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6363 if (err < 0)
6364 goto unlock;
6365
6366 if (!changed)
6367 goto unlock;
6368
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006369 err = new_options(hdev, sk);
6370
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006371 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006372 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006373
Marcel Holtmann516018a2015-03-13 02:11:04 -07006374 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006375 hci_dev_set_flag(hdev, HCI_CONFIG);
6376 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006377
6378 queue_work(hdev->req_workqueue, &hdev->power_on);
6379 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006380 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006381 mgmt_index_added(hdev);
6382 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006383 }
6384
6385unlock:
6386 hci_dev_unlock(hdev);
6387 return err;
6388}
6389
Marcel Holtmann9713c172014-07-06 12:11:15 +02006390static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6391 void *data, u16 len)
6392{
6393 struct mgmt_cp_set_public_address *cp = data;
6394 bool changed;
6395 int err;
6396
6397 BT_DBG("%s", hdev->name);
6398
6399 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006400 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6401 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006402
6403 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006404 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6405 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006406
6407 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006408 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6409 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006410
6411 hci_dev_lock(hdev);
6412
6413 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6414 bacpy(&hdev->public_addr, &cp->bdaddr);
6415
6416 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6417 if (err < 0)
6418 goto unlock;
6419
6420 if (!changed)
6421 goto unlock;
6422
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006423 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006424 err = new_options(hdev, sk);
6425
6426 if (is_configured(hdev)) {
6427 mgmt_index_removed(hdev);
6428
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006429 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006430
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006431 hci_dev_set_flag(hdev, HCI_CONFIG);
6432 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006433
6434 queue_work(hdev->req_workqueue, &hdev->power_on);
6435 }
6436
6437unlock:
6438 hci_dev_unlock(hdev);
6439 return err;
6440}
6441
Marcel Holtmannbea41602015-03-14 22:43:17 -07006442static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6443 u8 data_len)
6444{
6445 eir[eir_len++] = sizeof(type) + data_len;
6446 eir[eir_len++] = type;
6447 memcpy(&eir[eir_len], data, data_len);
6448 eir_len += data_len;
6449
6450 return eir_len;
6451}
6452
Johan Hedberg40f66c02015-04-07 21:52:22 +03006453static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
6454 u16 opcode, struct sk_buff *skb)
6455{
6456 const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
6457 struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
6458 u8 *h192, *r192, *h256, *r256;
6459 struct mgmt_pending_cmd *cmd;
6460 u16 eir_len;
6461 int err;
6462
6463 BT_DBG("%s status %u", hdev->name, status);
6464
6465 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
6466 if (!cmd)
6467 return;
6468
6469 mgmt_cp = cmd->param;
6470
6471 if (status) {
6472 status = mgmt_status(status);
6473 eir_len = 0;
6474
6475 h192 = NULL;
6476 r192 = NULL;
6477 h256 = NULL;
6478 r256 = NULL;
6479 } else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
6480 struct hci_rp_read_local_oob_data *rp;
6481
6482 if (skb->len != sizeof(*rp)) {
6483 status = MGMT_STATUS_FAILED;
6484 eir_len = 0;
6485 } else {
6486 status = MGMT_STATUS_SUCCESS;
6487 rp = (void *)skb->data;
6488
6489 eir_len = 5 + 18 + 18;
6490 h192 = rp->hash;
6491 r192 = rp->rand;
6492 h256 = NULL;
6493 r256 = NULL;
6494 }
6495 } else {
6496 struct hci_rp_read_local_oob_ext_data *rp;
6497
6498 if (skb->len != sizeof(*rp)) {
6499 status = MGMT_STATUS_FAILED;
6500 eir_len = 0;
6501 } else {
6502 status = MGMT_STATUS_SUCCESS;
6503 rp = (void *)skb->data;
6504
6505 if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
6506 eir_len = 5 + 18 + 18;
6507 h192 = NULL;
6508 r192 = NULL;
6509 } else {
6510 eir_len = 5 + 18 + 18 + 18 + 18;
6511 h192 = rp->hash192;
6512 r192 = rp->rand192;
6513 }
6514
6515 h256 = rp->hash256;
6516 r256 = rp->rand256;
6517 }
6518 }
6519
6520 mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
6521 if (!mgmt_rp)
6522 goto done;
6523
6524 if (status)
6525 goto send_rsp;
6526
6527 eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
6528 hdev->dev_class, 3);
6529
6530 if (h192 && r192) {
6531 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6532 EIR_SSP_HASH_C192, h192, 16);
6533 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6534 EIR_SSP_RAND_R192, r192, 16);
6535 }
6536
6537 if (h256 && r256) {
6538 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6539 EIR_SSP_HASH_C256, h256, 16);
6540 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6541 EIR_SSP_RAND_R256, r256, 16);
6542 }
6543
6544send_rsp:
6545 mgmt_rp->type = mgmt_cp->type;
6546 mgmt_rp->eir_len = cpu_to_le16(eir_len);
6547
6548 err = mgmt_cmd_complete(cmd->sk, hdev->id,
6549 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
6550 mgmt_rp, sizeof(*mgmt_rp) + eir_len);
6551 if (err < 0 || status)
6552 goto done;
6553
6554 hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
6555
6556 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6557 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
6558 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
6559done:
6560 kfree(mgmt_rp);
6561 mgmt_pending_remove(cmd);
6562}
6563
6564static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
6565 struct mgmt_cp_read_local_oob_ext_data *cp)
6566{
6567 struct mgmt_pending_cmd *cmd;
6568 struct hci_request req;
6569 int err;
6570
6571 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
6572 cp, sizeof(*cp));
6573 if (!cmd)
6574 return -ENOMEM;
6575
6576 hci_req_init(&req, hdev);
6577
6578 if (bredr_sc_enabled(hdev))
6579 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
6580 else
6581 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
6582
6583 err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
6584 if (err < 0) {
6585 mgmt_pending_remove(cmd);
6586 return err;
6587 }
6588
6589 return 0;
6590}
6591
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006592static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6593 void *data, u16 data_len)
6594{
6595 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6596 struct mgmt_rp_read_local_oob_ext_data *rp;
6597 size_t rp_len;
6598 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006599 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006600 int err;
6601
6602 BT_DBG("%s", hdev->name);
6603
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006604 if (hdev_is_powered(hdev)) {
6605 switch (cp->type) {
6606 case BIT(BDADDR_BREDR):
6607 status = mgmt_bredr_support(hdev);
6608 if (status)
6609 eir_len = 0;
6610 else
6611 eir_len = 5;
6612 break;
6613 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6614 status = mgmt_le_support(hdev);
6615 if (status)
6616 eir_len = 0;
6617 else
6618 eir_len = 9 + 3 + 18 + 18 + 3;
6619 break;
6620 default:
6621 status = MGMT_STATUS_INVALID_PARAMS;
6622 eir_len = 0;
6623 break;
6624 }
6625 } else {
6626 status = MGMT_STATUS_NOT_POWERED;
6627 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006628 }
6629
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006630 rp_len = sizeof(*rp) + eir_len;
6631 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006632 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006633 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006634
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006635 if (status)
6636 goto complete;
6637
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006638 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006639
6640 eir_len = 0;
6641 switch (cp->type) {
6642 case BIT(BDADDR_BREDR):
Johan Hedberg40f66c02015-04-07 21:52:22 +03006643 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
6644 err = read_local_ssp_oob_req(hdev, sk, cp);
6645 hci_dev_unlock(hdev);
6646 if (!err)
6647 goto done;
6648
6649 status = MGMT_STATUS_FAILED;
6650 goto complete;
6651 } else {
6652 eir_len = eir_append_data(rp->eir, eir_len,
6653 EIR_CLASS_OF_DEV,
6654 hdev->dev_class, 3);
6655 }
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006656 break;
6657 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006658 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6659 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006660 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006661 status = MGMT_STATUS_FAILED;
6662 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006663 }
6664
Marcel Holtmanne2135682015-04-02 12:00:58 -07006665 /* This should return the active RPA, but since the RPA
6666 * is only programmed on demand, it is really hard to fill
6667 * this in at the moment. For now disallow retrieving
6668 * local out-of-band data when privacy is in use.
6669 *
6670 * Returning the identity address will not help here since
6671 * pairing happens before the identity resolving key is
6672 * known and thus the connection establishment happens
6673 * based on the RPA and not the identity address.
6674 */
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006675 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
Marcel Holtmanne2135682015-04-02 12:00:58 -07006676 hci_dev_unlock(hdev);
6677 status = MGMT_STATUS_REJECTED;
6678 goto complete;
6679 }
6680
6681 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6682 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6683 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6684 bacmp(&hdev->static_addr, BDADDR_ANY))) {
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006685 memcpy(addr, &hdev->static_addr, 6);
6686 addr[6] = 0x01;
6687 } else {
6688 memcpy(addr, &hdev->bdaddr, 6);
6689 addr[6] = 0x00;
6690 }
6691
6692 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6693 addr, sizeof(addr));
6694
6695 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6696 role = 0x02;
6697 else
6698 role = 0x01;
6699
6700 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6701 &role, sizeof(role));
6702
Marcel Holtmann5082a592015-03-16 12:39:00 -07006703 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6704 eir_len = eir_append_data(rp->eir, eir_len,
6705 EIR_LE_SC_CONFIRM,
6706 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006707
Marcel Holtmann5082a592015-03-16 12:39:00 -07006708 eir_len = eir_append_data(rp->eir, eir_len,
6709 EIR_LE_SC_RANDOM,
6710 rand, sizeof(rand));
6711 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006712
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006713 flags = get_adv_discov_flags(hdev);
6714
6715 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6716 flags |= LE_AD_NO_BREDR;
6717
6718 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6719 &flags, sizeof(flags));
6720 break;
6721 }
6722
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006723 hci_dev_unlock(hdev);
6724
Marcel Holtmann72000df2015-03-16 16:11:21 -07006725 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6726
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006727 status = MGMT_STATUS_SUCCESS;
6728
6729complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006730 rp->type = cp->type;
6731 rp->eir_len = cpu_to_le16(eir_len);
6732
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006733 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006734 status, rp, sizeof(*rp) + eir_len);
6735 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006736 goto done;
6737
6738 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6739 rp, sizeof(*rp) + eir_len,
6740 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006741
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006742done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006743 kfree(rp);
6744
6745 return err;
6746}
6747
Arman Uguray089fa8c2015-03-25 18:53:45 -07006748static u32 get_supported_adv_flags(struct hci_dev *hdev)
6749{
6750 u32 flags = 0;
6751
6752 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6753 flags |= MGMT_ADV_FLAG_DISCOV;
6754 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6755 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6756
6757 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6758 flags |= MGMT_ADV_FLAG_TX_POWER;
6759
6760 return flags;
6761}
6762
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006763static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6764 void *data, u16 data_len)
6765{
6766 struct mgmt_rp_read_adv_features *rp;
6767 size_t rp_len;
6768 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006769 bool instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006770 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006771
6772 BT_DBG("%s", hdev->name);
6773
Arman Uguray089fa8c2015-03-25 18:53:45 -07006774 if (!lmp_le_capable(hdev))
6775 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6776 MGMT_STATUS_REJECTED);
6777
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006778 hci_dev_lock(hdev);
6779
6780 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006781
6782 /* Currently only one instance is supported, so just add 1 to the
6783 * response length.
6784 */
6785 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6786 if (instance)
6787 rp_len++;
6788
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006789 rp = kmalloc(rp_len, GFP_ATOMIC);
6790 if (!rp) {
6791 hci_dev_unlock(hdev);
6792 return -ENOMEM;
6793 }
6794
Arman Uguray089fa8c2015-03-25 18:53:45 -07006795 supported_flags = get_supported_adv_flags(hdev);
6796
6797 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006798 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6799 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Florian Grandeld2609b32015-06-18 03:16:34 +02006800 rp->max_instances = HCI_MAX_ADV_INSTANCES;
Arman Uguray24b4f382015-03-23 15:57:12 -07006801
6802 /* Currently only one instance is supported, so simply return the
6803 * current instance number.
6804 */
6805 if (instance) {
6806 rp->num_instances = 1;
6807 rp->instance[0] = 1;
6808 } else {
6809 rp->num_instances = 0;
6810 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006811
6812 hci_dev_unlock(hdev);
6813
6814 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6815 MGMT_STATUS_SUCCESS, rp, rp_len);
6816
6817 kfree(rp);
6818
6819 return err;
6820}
6821
Arman Uguray4117ed72015-03-23 15:57:14 -07006822static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006823 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006824{
Arman Uguray4117ed72015-03-23 15:57:14 -07006825 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006826 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006827 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006828 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006829 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6830 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006831
Arman Uguray807ec772015-03-25 18:53:42 -07006832 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006833 flags_managed = true;
6834 max_len -= 3;
6835 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006836
Arman Uguray5507e352015-03-25 18:53:44 -07006837 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6838 tx_power_managed = true;
6839 max_len -= 3;
6840 }
6841
Arman Uguray4117ed72015-03-23 15:57:14 -07006842 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006843 return false;
6844
Arman Uguray4117ed72015-03-23 15:57:14 -07006845 /* Make sure that the data is correctly formatted. */
6846 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6847 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006848
Arman Ugurayb44133f2015-03-25 18:53:41 -07006849 if (flags_managed && data[i + 1] == EIR_FLAGS)
6850 return false;
6851
Arman Uguray5507e352015-03-25 18:53:44 -07006852 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6853 return false;
6854
Arman Uguray24b4f382015-03-23 15:57:12 -07006855 /* If the current field length would exceed the total data
6856 * length, then it's invalid.
6857 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006858 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006859 return false;
6860 }
6861
6862 return true;
6863}
6864
Arman Uguray24b4f382015-03-23 15:57:12 -07006865static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6866 u16 opcode)
6867{
6868 struct mgmt_pending_cmd *cmd;
6869 struct mgmt_rp_add_advertising rp;
6870
6871 BT_DBG("status %d", status);
6872
6873 hci_dev_lock(hdev);
6874
6875 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6876
6877 if (status) {
6878 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6879 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6880 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6881 }
6882
6883 if (!cmd)
6884 goto unlock;
6885
6886 rp.instance = 0x01;
6887
6888 if (status)
6889 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6890 mgmt_status(status));
6891 else
6892 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6893 mgmt_status(status), &rp, sizeof(rp));
6894
6895 mgmt_pending_remove(cmd);
6896
6897unlock:
6898 hci_dev_unlock(hdev);
6899}
6900
Florian Grandel5d900e42015-06-18 03:16:35 +02006901void mgmt_adv_timeout_expired(struct hci_dev *hdev)
Arman Uguray912098a2015-03-23 15:57:15 -07006902{
Florian Grandel5d900e42015-06-18 03:16:35 +02006903 hdev->adv_instance_timeout = 0;
Arman Uguray912098a2015-03-23 15:57:15 -07006904
6905 hci_dev_lock(hdev);
6906 clear_adv_instance(hdev);
6907 hci_dev_unlock(hdev);
6908}
6909
Arman Uguray24b4f382015-03-23 15:57:12 -07006910static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6911 void *data, u16 data_len)
6912{
6913 struct mgmt_cp_add_advertising *cp = data;
6914 struct mgmt_rp_add_advertising rp;
6915 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006916 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006917 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006918 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006919 int err;
6920 struct mgmt_pending_cmd *cmd;
6921 struct hci_request req;
6922
6923 BT_DBG("%s", hdev->name);
6924
6925 status = mgmt_le_support(hdev);
6926 if (status)
6927 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6928 status);
6929
6930 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006931 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006932
Arman Uguray089fa8c2015-03-25 18:53:45 -07006933 /* The current implementation only supports adding one instance and only
6934 * a subset of the specified flags.
6935 */
6936 supported_flags = get_supported_adv_flags(hdev);
6937 if (cp->instance != 0x01 || (flags & ~supported_flags))
Arman Uguray24b4f382015-03-23 15:57:12 -07006938 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6939 MGMT_STATUS_INVALID_PARAMS);
6940
6941 hci_dev_lock(hdev);
6942
Arman Uguray912098a2015-03-23 15:57:15 -07006943 if (timeout && !hdev_is_powered(hdev)) {
6944 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6945 MGMT_STATUS_REJECTED);
6946 goto unlock;
6947 }
6948
Arman Uguray24b4f382015-03-23 15:57:12 -07006949 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006950 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006951 pending_find(MGMT_OP_SET_LE, hdev)) {
6952 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6953 MGMT_STATUS_BUSY);
6954 goto unlock;
6955 }
6956
Arman Ugurayb44133f2015-03-25 18:53:41 -07006957 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006958 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006959 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006960 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6961 MGMT_STATUS_INVALID_PARAMS);
6962 goto unlock;
6963 }
6964
6965 hdev->adv_instance.flags = flags;
6966 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6967 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6968
6969 if (cp->adv_data_len)
6970 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6971
6972 if (cp->scan_rsp_len)
6973 memcpy(hdev->adv_instance.scan_rsp_data,
6974 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6975
Florian Grandel5d900e42015-06-18 03:16:35 +02006976 if (hdev->adv_instance_timeout)
6977 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07006978
Florian Grandel5d900e42015-06-18 03:16:35 +02006979 hdev->adv_instance_timeout = timeout;
Arman Uguray912098a2015-03-23 15:57:15 -07006980
6981 if (timeout)
6982 queue_delayed_work(hdev->workqueue,
Florian Grandel5d900e42015-06-18 03:16:35 +02006983 &hdev->adv_instance_expire,
Arman Uguray912098a2015-03-23 15:57:15 -07006984 msecs_to_jiffies(timeout * 1000));
6985
Arman Uguray24b4f382015-03-23 15:57:12 -07006986 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
6987 advertising_added(sk, hdev, 1);
6988
6989 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
6990 * we have no HCI communication to make. Simply return.
6991 */
6992 if (!hdev_is_powered(hdev) ||
6993 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
6994 rp.instance = 0x01;
6995 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6996 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
6997 goto unlock;
6998 }
6999
7000 /* We're good to go, update advertising data, parameters, and start
7001 * advertising.
7002 */
7003 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
7004 data_len);
7005 if (!cmd) {
7006 err = -ENOMEM;
7007 goto unlock;
7008 }
7009
7010 hci_req_init(&req, hdev);
7011
7012 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07007013 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007014 enable_advertising(&req);
7015
7016 err = hci_req_run(&req, add_advertising_complete);
7017 if (err < 0)
7018 mgmt_pending_remove(cmd);
7019
7020unlock:
7021 hci_dev_unlock(hdev);
7022
7023 return err;
7024}
7025
Arman Ugurayda9293352015-03-23 15:57:13 -07007026static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
7027 u16 opcode)
7028{
7029 struct mgmt_pending_cmd *cmd;
7030 struct mgmt_rp_remove_advertising rp;
7031
7032 BT_DBG("status %d", status);
7033
7034 hci_dev_lock(hdev);
7035
7036 /* A failure status here only means that we failed to disable
7037 * advertising. Otherwise, the advertising instance has been removed,
7038 * so report success.
7039 */
7040 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
7041 if (!cmd)
7042 goto unlock;
7043
7044 rp.instance = 1;
7045
7046 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
7047 &rp, sizeof(rp));
7048 mgmt_pending_remove(cmd);
7049
7050unlock:
7051 hci_dev_unlock(hdev);
7052}
7053
7054static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
7055 void *data, u16 data_len)
7056{
7057 struct mgmt_cp_remove_advertising *cp = data;
7058 struct mgmt_rp_remove_advertising rp;
7059 int err;
7060 struct mgmt_pending_cmd *cmd;
7061 struct hci_request req;
7062
7063 BT_DBG("%s", hdev->name);
7064
7065 /* The current implementation only allows modifying instance no 1. A
7066 * value of 0 indicates that all instances should be cleared.
7067 */
7068 if (cp->instance > 1)
7069 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7070 MGMT_STATUS_INVALID_PARAMS);
7071
7072 hci_dev_lock(hdev);
7073
7074 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
7075 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
7076 pending_find(MGMT_OP_SET_LE, hdev)) {
7077 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7078 MGMT_STATUS_BUSY);
7079 goto unlock;
7080 }
7081
7082 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
7083 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7084 MGMT_STATUS_INVALID_PARAMS);
7085 goto unlock;
7086 }
7087
Florian Grandel5d900e42015-06-18 03:16:35 +02007088 if (hdev->adv_instance_timeout)
7089 cancel_delayed_work(&hdev->adv_instance_expire);
Arman Uguray912098a2015-03-23 15:57:15 -07007090
Arman Ugurayda9293352015-03-23 15:57:13 -07007091 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
7092
7093 advertising_removed(sk, hdev, 1);
7094
7095 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
7096
7097 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7098 * we have no HCI communication to make. Simply return.
7099 */
7100 if (!hdev_is_powered(hdev) ||
7101 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7102 rp.instance = 1;
7103 err = mgmt_cmd_complete(sk, hdev->id,
7104 MGMT_OP_REMOVE_ADVERTISING,
7105 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7106 goto unlock;
7107 }
7108
7109 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
7110 data_len);
7111 if (!cmd) {
7112 err = -ENOMEM;
7113 goto unlock;
7114 }
7115
7116 hci_req_init(&req, hdev);
7117 disable_advertising(&req);
7118
7119 err = hci_req_run(&req, remove_advertising_complete);
7120 if (err < 0)
7121 mgmt_pending_remove(cmd);
7122
7123unlock:
7124 hci_dev_unlock(hdev);
7125
7126 return err;
7127}
7128
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007129static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007130 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007131 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007132 HCI_MGMT_NO_HDEV |
7133 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007134 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007135 HCI_MGMT_NO_HDEV |
7136 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007137 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007138 HCI_MGMT_NO_HDEV |
7139 HCI_MGMT_UNTRUSTED },
7140 { read_controller_info, MGMT_READ_INFO_SIZE,
7141 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007142 { set_powered, MGMT_SETTING_SIZE },
7143 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7144 { set_connectable, MGMT_SETTING_SIZE },
7145 { set_fast_connectable, MGMT_SETTING_SIZE },
7146 { set_bondable, MGMT_SETTING_SIZE },
7147 { set_link_security, MGMT_SETTING_SIZE },
7148 { set_ssp, MGMT_SETTING_SIZE },
7149 { set_hs, MGMT_SETTING_SIZE },
7150 { set_le, MGMT_SETTING_SIZE },
7151 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7152 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7153 { add_uuid, MGMT_ADD_UUID_SIZE },
7154 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007155 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7156 HCI_MGMT_VAR_LEN },
7157 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7158 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007159 { disconnect, MGMT_DISCONNECT_SIZE },
7160 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7161 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7162 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7163 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7164 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7165 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7166 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7167 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7168 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7169 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7170 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007171 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7172 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7173 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007174 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7175 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7176 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7177 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7178 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7179 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7180 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7181 { set_advertising, MGMT_SETTING_SIZE },
7182 { set_bredr, MGMT_SETTING_SIZE },
7183 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7184 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7185 { set_secure_conn, MGMT_SETTING_SIZE },
7186 { set_debug_keys, MGMT_SETTING_SIZE },
7187 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007188 { load_irks, MGMT_LOAD_IRKS_SIZE,
7189 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007190 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7191 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7192 { add_device, MGMT_ADD_DEVICE_SIZE },
7193 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007194 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7195 HCI_MGMT_VAR_LEN },
7196 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007197 HCI_MGMT_NO_HDEV |
7198 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007199 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007200 HCI_MGMT_UNCONFIGURED |
7201 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007202 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7203 HCI_MGMT_UNCONFIGURED },
7204 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7205 HCI_MGMT_UNCONFIGURED },
7206 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7207 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007208 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007209 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007210 HCI_MGMT_NO_HDEV |
7211 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007212 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007213 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7214 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007215 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007216};
7217
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007218void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007219{
Marcel Holtmannced85542015-03-14 19:27:56 -07007220 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007221
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007222 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7223 return;
7224
Marcel Holtmannf9207332015-03-14 19:27:55 -07007225 switch (hdev->dev_type) {
7226 case HCI_BREDR:
7227 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7228 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7229 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007230 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007231 } else {
7232 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7233 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007234 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007235 }
7236 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007237 case HCI_AMP:
7238 ev.type = 0x02;
7239 break;
7240 default:
7241 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007242 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007243
7244 ev.bus = hdev->bus;
7245
7246 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7247 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007248}
7249
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007250void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007251{
Marcel Holtmannced85542015-03-14 19:27:56 -07007252 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007253 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007254
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007255 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7256 return;
7257
Marcel Holtmannf9207332015-03-14 19:27:55 -07007258 switch (hdev->dev_type) {
7259 case HCI_BREDR:
7260 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007261
Marcel Holtmannf9207332015-03-14 19:27:55 -07007262 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7263 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7264 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007265 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007266 } else {
7267 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7268 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007269 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007270 }
7271 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007272 case HCI_AMP:
7273 ev.type = 0x02;
7274 break;
7275 default:
7276 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007277 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007278
7279 ev.bus = hdev->bus;
7280
7281 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7282 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007283}
7284
Andre Guedes6046dc32014-02-26 20:21:51 -03007285/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007286static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007287{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007288 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007289 struct hci_conn_params *p;
7290
7291 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007292 /* Needed for AUTO_OFF case where might not "really"
7293 * have been powered off.
7294 */
7295 list_del_init(&p->action);
7296
7297 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007298 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007299 case HCI_AUTO_CONN_ALWAYS:
7300 list_add(&p->action, &hdev->pend_le_conns);
7301 break;
7302 case HCI_AUTO_CONN_REPORT:
7303 list_add(&p->action, &hdev->pend_le_reports);
7304 break;
7305 default:
7306 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007307 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007308 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007309
Johan Hedberg2cf22212014-12-19 22:26:00 +02007310 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007311}
7312
Marcel Holtmann1904a852015-01-11 13:50:44 -08007313static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007314{
7315 struct cmd_lookup match = { NULL, hdev };
7316
7317 BT_DBG("status 0x%02x", status);
7318
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007319 if (!status) {
7320 /* Register the available SMP channels (BR/EDR and LE) only
7321 * when successfully powering on the controller. This late
7322 * registration is required so that LE SMP can clearly
7323 * decide if the public address or static address is used.
7324 */
7325 smp_register(hdev);
7326 }
7327
Johan Hedberg229ab392013-03-15 17:06:53 -05007328 hci_dev_lock(hdev);
7329
7330 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7331
7332 new_settings(hdev, match.sk);
7333
7334 hci_dev_unlock(hdev);
7335
7336 if (match.sk)
7337 sock_put(match.sk);
7338}
7339
Johan Hedberg70da6242013-03-15 17:06:51 -05007340static int powered_update_hci(struct hci_dev *hdev)
7341{
Johan Hedberg890ea892013-03-15 17:06:52 -05007342 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007343 u8 link_sec;
7344
Johan Hedberg890ea892013-03-15 17:06:52 -05007345 hci_req_init(&req, hdev);
7346
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007347 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007348 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007349 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007350
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007351 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007352
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007353 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7354 u8 support = 0x01;
7355
7356 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7357 sizeof(support), &support);
7358 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007359 }
7360
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007361 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007362 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007363 struct hci_cp_write_le_host_supported cp;
7364
Marcel Holtmann32226e42014-07-24 20:04:16 +02007365 cp.le = 0x01;
7366 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007367
7368 /* Check first if we already have the right
7369 * host state (host features set)
7370 */
7371 if (cp.le != lmp_host_le_capable(hdev) ||
7372 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007373 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7374 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007375 }
7376
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007377 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007378 /* Make sure the controller has a good default for
7379 * advertising data. This also applies to the case
7380 * where BR/EDR was toggled during the AUTO_OFF phase.
7381 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007382 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007383 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007384 update_scan_rsp_data(&req);
7385 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007386
Arman Uguray24b4f382015-03-23 15:57:12 -07007387 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7388 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007389 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007390
7391 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007392 }
7393
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007394 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007395 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007396 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7397 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007398
7399 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007400 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007401 write_fast_connectable(&req, true);
7402 else
7403 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007404 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007405 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007406 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007407 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007408 }
7409
Johan Hedberg229ab392013-03-15 17:06:53 -05007410 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007411}
7412
Johan Hedberg744cf192011-11-08 20:40:14 +02007413int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007414{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007415 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007416 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007417 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007418
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007419 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007420 return 0;
7421
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007422 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007423 if (powered_update_hci(hdev) == 0)
7424 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007425
Johan Hedberg229ab392013-03-15 17:06:53 -05007426 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7427 &match);
7428 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007429 }
7430
Johan Hedberg229ab392013-03-15 17:06:53 -05007431 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007432
7433 /* If the power off is because of hdev unregistration let
7434 * use the appropriate INVALID_INDEX status. Otherwise use
7435 * NOT_POWERED. We cover both scenarios here since later in
7436 * mgmt_index_removed() any hci_conn callbacks will have already
7437 * been triggered, potentially causing misleading DISCONNECTED
7438 * status responses.
7439 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007440 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007441 status = MGMT_STATUS_INVALID_INDEX;
7442 else
7443 status = MGMT_STATUS_NOT_POWERED;
7444
7445 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007446
7447 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007448 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7449 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007450
7451new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007452 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007453
7454 if (match.sk)
7455 sock_put(match.sk);
7456
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007457 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007458}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007459
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007460void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007461{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007462 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007463 u8 status;
7464
Johan Hedberg333ae952015-03-17 13:48:47 +02007465 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007466 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007467 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007468
7469 if (err == -ERFKILL)
7470 status = MGMT_STATUS_RFKILLED;
7471 else
7472 status = MGMT_STATUS_FAILED;
7473
Johan Hedberga69e8372015-03-06 21:08:53 +02007474 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007475
7476 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007477}
7478
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007479void mgmt_discoverable_timeout(struct hci_dev *hdev)
7480{
7481 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007482
7483 hci_dev_lock(hdev);
7484
7485 /* When discoverable timeout triggers, then just make sure
7486 * the limited discoverable flag is cleared. Even in the case
7487 * of a timeout triggered from general discoverable, it is
7488 * safe to unconditionally clear the flag.
7489 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007490 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7491 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007492
7493 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007494 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007495 u8 scan = SCAN_PAGE;
7496 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7497 sizeof(scan), &scan);
7498 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007499 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007500
7501 /* Advertising instances don't use the global discoverable setting, so
7502 * only update AD if advertising was enabled using Set Advertising.
7503 */
7504 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7505 update_adv_data(&req);
7506
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007507 hci_req_run(&req, NULL);
7508
7509 hdev->discov_timeout = 0;
7510
Johan Hedberg9a43e252013-10-20 19:00:07 +03007511 new_settings(hdev, NULL);
7512
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007513 hci_dev_unlock(hdev);
7514}
7515
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007516void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7517 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007518{
Johan Hedberg86742e12011-11-07 23:13:38 +02007519 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007520
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007521 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007522
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007523 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007524 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007525 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007526 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007527 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007528 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007529
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007530 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007531}
Johan Hedbergf7520542011-01-20 12:34:39 +02007532
Johan Hedbergd7b25452014-05-23 13:19:53 +03007533static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7534{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007535 switch (ltk->type) {
7536 case SMP_LTK:
7537 case SMP_LTK_SLAVE:
7538 if (ltk->authenticated)
7539 return MGMT_LTK_AUTHENTICATED;
7540 return MGMT_LTK_UNAUTHENTICATED;
7541 case SMP_LTK_P256:
7542 if (ltk->authenticated)
7543 return MGMT_LTK_P256_AUTH;
7544 return MGMT_LTK_P256_UNAUTH;
7545 case SMP_LTK_P256_DEBUG:
7546 return MGMT_LTK_P256_DEBUG;
7547 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007548
7549 return MGMT_LTK_UNAUTHENTICATED;
7550}
7551
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007552void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007553{
7554 struct mgmt_ev_new_long_term_key ev;
7555
7556 memset(&ev, 0, sizeof(ev));
7557
Marcel Holtmann5192d302014-02-19 17:11:58 -08007558 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007559 * without providing an identity resolving key don't require
Marcel Holtmann5192d302014-02-19 17:11:58 -08007560 * to store long term keys. Their addresses will change the
7561 * next time around.
7562 *
7563 * Only when a remote device provides an identity address
7564 * make sure the long term key is stored. If the remote
7565 * identity is known, the long term keys are internally
7566 * mapped to the identity address. So allow static random
7567 * and public addresses here.
7568 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007569 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7570 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7571 ev.store_hint = 0x00;
7572 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007573 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007574
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007575 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007576 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007577 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007578 ev.key.enc_size = key->enc_size;
7579 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007580 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007581
Johan Hedberg2ceba532014-06-16 19:25:16 +03007582 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007583 ev.key.master = 1;
7584
Johan Hedberg1fc62c52015-06-10 11:11:20 +03007585 /* Make sure we copy only the significant bytes based on the
7586 * encryption key size, and set the rest of the value to zeroes.
7587 */
7588 memcpy(ev.key.val, key->val, sizeof(key->enc_size));
7589 memset(ev.key.val + key->enc_size, 0,
7590 sizeof(ev.key.val) - key->enc_size);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007591
Marcel Holtmann083368f2013-10-15 14:26:29 -07007592 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007593}
7594
Johan Hedberg95fbac82014-02-19 15:18:31 +02007595void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7596{
7597 struct mgmt_ev_new_irk ev;
7598
7599 memset(&ev, 0, sizeof(ev));
7600
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007601 /* For identity resolving keys from devices that are already
7602 * using a public address or static random address, do not
7603 * ask for storing this key. The identity resolving key really
Florian Grandelf72186d2015-05-26 03:31:09 +02007604 * is only mandatory for devices using resolvable random
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007605 * addresses.
7606 *
7607 * Storing all identity resolving keys has the downside that
7608 * they will be also loaded on next boot of they system. More
7609 * identity resolving keys, means more time during scanning is
7610 * needed to actually resolve these addresses.
7611 */
7612 if (bacmp(&irk->rpa, BDADDR_ANY))
7613 ev.store_hint = 0x01;
7614 else
7615 ev.store_hint = 0x00;
7616
Johan Hedberg95fbac82014-02-19 15:18:31 +02007617 bacpy(&ev.rpa, &irk->rpa);
7618 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7619 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7620 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7621
7622 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7623}
7624
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007625void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7626 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007627{
7628 struct mgmt_ev_new_csrk ev;
7629
7630 memset(&ev, 0, sizeof(ev));
7631
7632 /* Devices using resolvable or non-resolvable random addresses
Florian Grandelf72186d2015-05-26 03:31:09 +02007633 * without providing an identity resolving key don't require
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007634 * to store signature resolving keys. Their addresses will change
7635 * the next time around.
7636 *
7637 * Only when a remote device provides an identity address
7638 * make sure the signature resolving key is stored. So allow
7639 * static random and public addresses here.
7640 */
7641 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7642 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7643 ev.store_hint = 0x00;
7644 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007645 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007646
7647 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7648 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007649 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007650 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7651
7652 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7653}
7654
Andre Guedesffb5a8272014-07-01 18:10:11 -03007655void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007656 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7657 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007658{
7659 struct mgmt_ev_new_conn_param ev;
7660
Johan Hedbergc103aea2014-07-02 17:37:34 +03007661 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7662 return;
7663
Andre Guedesffb5a8272014-07-01 18:10:11 -03007664 memset(&ev, 0, sizeof(ev));
7665 bacpy(&ev.addr.bdaddr, bdaddr);
7666 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007667 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007668 ev.min_interval = cpu_to_le16(min_interval);
7669 ev.max_interval = cpu_to_le16(max_interval);
7670 ev.latency = cpu_to_le16(latency);
7671 ev.timeout = cpu_to_le16(timeout);
7672
7673 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7674}
7675
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007676void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7677 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007678{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007679 char buf[512];
7680 struct mgmt_ev_device_connected *ev = (void *) buf;
7681 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007682
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007683 bacpy(&ev->addr.bdaddr, &conn->dst);
7684 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007685
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007686 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007687
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007688 /* We must ensure that the EIR Data fields are ordered and
7689 * unique. Keep it simple for now and avoid the problem by not
7690 * adding any BR/EDR data to the LE adv.
7691 */
7692 if (conn->le_adv_data_len > 0) {
7693 memcpy(&ev->eir[eir_len],
7694 conn->le_adv_data, conn->le_adv_data_len);
7695 eir_len = conn->le_adv_data_len;
7696 } else {
7697 if (name_len > 0)
7698 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7699 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007700
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007701 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007702 eir_len = eir_append_data(ev->eir, eir_len,
7703 EIR_CLASS_OF_DEV,
7704 conn->dev_class, 3);
7705 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007706
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007707 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007708
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007709 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7710 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007711}
7712
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007713static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007714{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007715 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007716
Johan Hedbergf5818c22014-12-05 13:36:02 +02007717 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007718
7719 *sk = cmd->sk;
7720 sock_hold(*sk);
7721
Johan Hedberga664b5b2011-02-19 12:06:02 -03007722 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007723}
7724
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007725static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007726{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007727 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007728 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007729
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007730 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7731
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007732 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007733 mgmt_pending_remove(cmd);
7734}
7735
Johan Hedberg84c61d92014-08-01 11:13:30 +03007736bool mgmt_powering_down(struct hci_dev *hdev)
7737{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007738 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007739 struct mgmt_mode *cp;
7740
Johan Hedberg333ae952015-03-17 13:48:47 +02007741 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007742 if (!cmd)
7743 return false;
7744
7745 cp = cmd->param;
7746 if (!cp->val)
7747 return true;
7748
7749 return false;
7750}
7751
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007752void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007753 u8 link_type, u8 addr_type, u8 reason,
7754 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007755{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007756 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007757 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007758
Johan Hedberg84c61d92014-08-01 11:13:30 +03007759 /* The connection is still in hci_conn_hash so test for 1
7760 * instead of 0 to know if this is the last one.
7761 */
7762 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7763 cancel_delayed_work(&hdev->power_off);
7764 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007765 }
7766
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007767 if (!mgmt_connected)
7768 return;
7769
Andre Guedes57eb7762013-10-30 19:01:41 -03007770 if (link_type != ACL_LINK && link_type != LE_LINK)
7771 return;
7772
Johan Hedberg744cf192011-11-08 20:40:14 +02007773 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007774
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007775 bacpy(&ev.addr.bdaddr, bdaddr);
7776 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7777 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007778
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007779 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007780
7781 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007782 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007783
Johan Hedberg124f6e32012-02-09 13:50:12 +02007784 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007785 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007786}
7787
Marcel Holtmann78929242013-10-06 23:55:47 -07007788void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7789 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007790{
Andre Guedes3655bba2013-10-30 19:01:40 -03007791 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7792 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007793 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007794
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007795 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7796 hdev);
7797
Johan Hedberg333ae952015-03-17 13:48:47 +02007798 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007799 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007800 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007801
Andre Guedes3655bba2013-10-30 19:01:40 -03007802 cp = cmd->param;
7803
7804 if (bacmp(bdaddr, &cp->addr.bdaddr))
7805 return;
7806
7807 if (cp->addr.type != bdaddr_type)
7808 return;
7809
Johan Hedbergf5818c22014-12-05 13:36:02 +02007810 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007811 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007812}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007813
Marcel Holtmann445608d2013-10-06 23:55:48 -07007814void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7815 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007816{
7817 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007818
Johan Hedberg84c61d92014-08-01 11:13:30 +03007819 /* The connection is still in hci_conn_hash so test for 1
7820 * instead of 0 to know if this is the last one.
7821 */
7822 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7823 cancel_delayed_work(&hdev->power_off);
7824 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007825 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007826
Johan Hedberg4c659c32011-11-07 23:13:39 +02007827 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007828 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007829 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007830
Marcel Holtmann445608d2013-10-06 23:55:48 -07007831 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007832}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007833
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007834void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007835{
7836 struct mgmt_ev_pin_code_request ev;
7837
Johan Hedbergd8457692012-02-17 14:24:57 +02007838 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007839 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007840 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007841
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007842 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007843}
7844
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007845void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7846 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007847{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007848 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007849
Johan Hedberg333ae952015-03-17 13:48:47 +02007850 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007851 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007852 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007853
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007854 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007855 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007856}
7857
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007858void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7859 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007860{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007861 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007862
Johan Hedberg333ae952015-03-17 13:48:47 +02007863 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007864 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007865 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007866
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007867 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007868 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007869}
Johan Hedberga5c29682011-02-19 12:05:57 -03007870
Johan Hedberg744cf192011-11-08 20:40:14 +02007871int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007872 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007873 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007874{
7875 struct mgmt_ev_user_confirm_request ev;
7876
Johan Hedberg744cf192011-11-08 20:40:14 +02007877 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007878
Johan Hedberg272d90d2012-02-09 15:26:12 +02007879 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007880 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007881 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007882 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007883
Johan Hedberg744cf192011-11-08 20:40:14 +02007884 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007885 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007886}
7887
Johan Hedberg272d90d2012-02-09 15:26:12 +02007888int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007889 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007890{
7891 struct mgmt_ev_user_passkey_request ev;
7892
7893 BT_DBG("%s", hdev->name);
7894
Johan Hedberg272d90d2012-02-09 15:26:12 +02007895 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007896 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007897
7898 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007899 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007900}
7901
Brian Gix0df4c182011-11-16 13:53:13 -08007902static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007903 u8 link_type, u8 addr_type, u8 status,
7904 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007905{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007906 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007907
Johan Hedberg333ae952015-03-17 13:48:47 +02007908 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007909 if (!cmd)
7910 return -ENOENT;
7911
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007912 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007913 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007914
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007915 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007916}
7917
Johan Hedberg744cf192011-11-08 20:40:14 +02007918int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007919 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007920{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007921 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007922 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007923}
7924
Johan Hedberg272d90d2012-02-09 15:26:12 +02007925int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007926 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007927{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007928 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007929 status,
7930 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007931}
Johan Hedberg2a611692011-02-19 12:06:00 -03007932
Brian Gix604086b2011-11-23 08:28:33 -08007933int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007934 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007935{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007936 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007937 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007938}
7939
Johan Hedberg272d90d2012-02-09 15:26:12 +02007940int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007941 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007942{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007943 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007944 status,
7945 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007946}
7947
Johan Hedberg92a25252012-09-06 18:39:26 +03007948int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7949 u8 link_type, u8 addr_type, u32 passkey,
7950 u8 entered)
7951{
7952 struct mgmt_ev_passkey_notify ev;
7953
7954 BT_DBG("%s", hdev->name);
7955
7956 bacpy(&ev.addr.bdaddr, bdaddr);
7957 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7958 ev.passkey = __cpu_to_le32(passkey);
7959 ev.entered = entered;
7960
7961 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7962}
7963
Johan Hedberge1e930f2014-09-08 17:09:49 -07007964void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007965{
7966 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007967 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007968 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007969
Johan Hedberge1e930f2014-09-08 17:09:49 -07007970 bacpy(&ev.addr.bdaddr, &conn->dst);
7971 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7972 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007973
Johan Hedberge1e930f2014-09-08 17:09:49 -07007974 cmd = find_pairing(conn);
7975
7976 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7977 cmd ? cmd->sk : NULL);
7978
Johan Hedberga511b352014-12-11 21:45:45 +02007979 if (cmd) {
7980 cmd->cmd_complete(cmd, status);
7981 mgmt_pending_remove(cmd);
7982 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007983}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007984
Marcel Holtmann464996a2013-10-15 14:26:24 -07007985void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007986{
7987 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007988 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007989
7990 if (status) {
7991 u8 mgmt_err = mgmt_status(status);
7992 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007993 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007994 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007995 }
7996
Marcel Holtmann464996a2013-10-15 14:26:24 -07007997 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007998 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007999 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008000 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02008001
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008002 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008003 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008004
Johan Hedberg47990ea2012-02-22 11:58:37 +02008005 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07008006 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008007
8008 if (match.sk)
8009 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008010}
8011
Johan Hedberg890ea892013-03-15 17:06:52 -05008012static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02008013{
Johan Hedberg890ea892013-03-15 17:06:52 -05008014 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008015 struct hci_cp_write_eir cp;
8016
Johan Hedberg976eb202012-10-24 21:12:01 +03008017 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05008018 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008019
Johan Hedbergc80da272012-02-22 15:38:48 +02008020 memset(hdev->eir, 0, sizeof(hdev->eir));
8021
Johan Hedbergcacaf522012-02-21 00:52:42 +02008022 memset(&cp, 0, sizeof(cp));
8023
Johan Hedberg890ea892013-03-15 17:06:52 -05008024 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02008025}
8026
Marcel Holtmann3e248562013-10-15 14:26:25 -07008027void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008028{
8029 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05008030 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008031 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008032
8033 if (status) {
8034 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008035
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008036 if (enable && hci_dev_test_and_clear_flag(hdev,
8037 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008038 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008039 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008040 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008041
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008042 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
8043 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008044 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008045 }
8046
8047 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07008048 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008049 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008050 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008051 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008052 changed = hci_dev_test_and_clear_flag(hdev,
8053 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008054 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008055 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008056 }
8057
8058 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
8059
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008060 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07008061 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008062
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02008063 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008064 sock_put(match.sk);
8065
Johan Hedberg890ea892013-03-15 17:06:52 -05008066 hci_req_init(&req, hdev);
8067
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008068 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
8069 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03008070 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
8071 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05008072 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008073 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05008074 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008075 }
Johan Hedberg890ea892013-03-15 17:06:52 -05008076
8077 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008078}
8079
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008080static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02008081{
8082 struct cmd_lookup *match = data;
8083
Johan Hedberg90e70452012-02-23 23:09:40 +02008084 if (match->sk == NULL) {
8085 match->sk = cmd->sk;
8086 sock_hold(match->sk);
8087 }
Johan Hedberg90e70452012-02-23 23:09:40 +02008088}
8089
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07008090void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
8091 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008092{
Johan Hedberg90e70452012-02-23 23:09:40 +02008093 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008094
Johan Hedberg92da6092013-03-15 17:06:55 -05008095 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
8096 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
8097 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02008098
8099 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008100 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
8101 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02008102
8103 if (match.sk)
8104 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008105}
8106
Marcel Holtmann7667da32013-10-15 14:26:27 -07008107void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02008108{
Johan Hedbergb312b1612011-03-16 14:29:37 +02008109 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008110 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008111
Johan Hedberg13928972013-03-15 17:07:00 -05008112 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07008113 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008114
8115 memset(&ev, 0, sizeof(ev));
8116 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008117 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008118
Johan Hedberg333ae952015-03-17 13:48:47 +02008119 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05008120 if (!cmd) {
8121 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02008122
Johan Hedberg13928972013-03-15 17:07:00 -05008123 /* If this is a HCI command related to powering on the
8124 * HCI dev don't send any mgmt signals.
8125 */
Johan Hedberg333ae952015-03-17 13:48:47 +02008126 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07008127 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008128 }
8129
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008130 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
8131 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008132}
Szymon Jancc35938b2011-03-22 13:12:21 +01008133
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008134static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
8135{
8136 int i;
8137
8138 for (i = 0; i < uuid_count; i++) {
8139 if (!memcmp(uuid, uuids[i], 16))
8140 return true;
8141 }
8142
8143 return false;
8144}
8145
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008146static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
8147{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008148 u16 parsed = 0;
8149
8150 while (parsed < eir_len) {
8151 u8 field_len = eir[0];
8152 u8 uuid[16];
8153 int i;
8154
8155 if (field_len == 0)
8156 break;
8157
8158 if (eir_len - parsed < field_len + 1)
8159 break;
8160
8161 switch (eir[1]) {
8162 case EIR_UUID16_ALL:
8163 case EIR_UUID16_SOME:
8164 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008165 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008166 uuid[13] = eir[i + 3];
8167 uuid[12] = eir[i + 2];
8168 if (has_uuid(uuid, uuid_count, uuids))
8169 return true;
8170 }
8171 break;
8172 case EIR_UUID32_ALL:
8173 case EIR_UUID32_SOME:
8174 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008175 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008176 uuid[15] = eir[i + 5];
8177 uuid[14] = eir[i + 4];
8178 uuid[13] = eir[i + 3];
8179 uuid[12] = eir[i + 2];
8180 if (has_uuid(uuid, uuid_count, uuids))
8181 return true;
8182 }
8183 break;
8184 case EIR_UUID128_ALL:
8185 case EIR_UUID128_SOME:
8186 for (i = 0; i + 17 <= field_len; i += 16) {
8187 memcpy(uuid, eir + i + 2, 16);
8188 if (has_uuid(uuid, uuid_count, uuids))
8189 return true;
8190 }
8191 break;
8192 }
8193
8194 parsed += field_len + 1;
8195 eir += field_len + 1;
8196 }
8197
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008198 return false;
8199}
8200
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008201static void restart_le_scan(struct hci_dev *hdev)
8202{
8203 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008204 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008205 return;
8206
8207 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8208 hdev->discovery.scan_start +
8209 hdev->discovery.scan_duration))
8210 return;
8211
8212 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8213 DISCOV_LE_RESTART_DELAY);
8214}
8215
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008216static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8217 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8218{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008219 /* If a RSSI threshold has been specified, and
8220 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8221 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8222 * is set, let it through for further processing, as we might need to
8223 * restart the scan.
8224 *
8225 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8226 * the results are also dropped.
8227 */
8228 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8229 (rssi == HCI_RSSI_INVALID ||
8230 (rssi < hdev->discovery.rssi &&
8231 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8232 return false;
8233
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008234 if (hdev->discovery.uuid_count != 0) {
8235 /* If a list of UUIDs is provided in filter, results with no
8236 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008237 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008238 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8239 hdev->discovery.uuids) &&
8240 !eir_has_uuids(scan_rsp, scan_rsp_len,
8241 hdev->discovery.uuid_count,
8242 hdev->discovery.uuids))
8243 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008244 }
8245
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008246 /* If duplicate filtering does not report RSSI changes, then restart
8247 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008248 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008249 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8250 restart_le_scan(hdev);
8251
8252 /* Validate RSSI value against the RSSI threshold once more. */
8253 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8254 rssi < hdev->discovery.rssi)
8255 return false;
8256 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008257
8258 return true;
8259}
8260
Marcel Holtmann901801b2013-10-06 23:55:51 -07008261void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008262 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8263 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008264{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008265 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008266 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008267 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008268
Johan Hedberg75ce2082014-07-02 22:42:01 +03008269 /* Don't send events for a non-kernel initiated discovery. With
8270 * LE one exception is if we have pend_le_reports > 0 in which
8271 * case we're doing passive scanning and want these events.
8272 */
8273 if (!hci_discovery_active(hdev)) {
8274 if (link_type == ACL_LINK)
8275 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008276 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008277 return;
8278 }
Andre Guedes12602d02013-04-30 15:29:40 -03008279
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008280 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008281 /* We are using service discovery */
8282 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8283 scan_rsp_len))
8284 return;
8285 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008286
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008287 /* Make sure that the buffer is big enough. The 5 extra bytes
8288 * are for the potential CoD field.
8289 */
8290 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008291 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008292
Johan Hedberg1dc06092012-01-15 21:01:23 +02008293 memset(buf, 0, sizeof(buf));
8294
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008295 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8296 * RSSI value was reported as 0 when not available. This behavior
8297 * is kept when using device discovery. This is required for full
8298 * backwards compatibility with the API.
8299 *
8300 * However when using service discovery, the value 127 will be
8301 * returned when the RSSI is not available.
8302 */
Szymon Janc91200e92015-01-22 16:57:05 +01008303 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8304 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008305 rssi = 0;
8306
Johan Hedberg841c5642014-07-07 12:45:54 +03008307 bacpy(&ev->addr.bdaddr, bdaddr);
8308 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008309 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008310 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008311
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008312 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008313 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008314 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008315
Johan Hedberg1dc06092012-01-15 21:01:23 +02008316 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8317 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008318 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008319
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008320 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008321 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008322 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008323
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008324 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8325 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008326
Marcel Holtmann901801b2013-10-06 23:55:51 -07008327 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008328}
Johan Hedberga88a9652011-03-30 13:18:12 +03008329
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008330void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8331 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008332{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008333 struct mgmt_ev_device_found *ev;
8334 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8335 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008336
Johan Hedbergb644ba32012-01-17 21:48:47 +02008337 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008338
Johan Hedbergb644ba32012-01-17 21:48:47 +02008339 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008340
Johan Hedbergb644ba32012-01-17 21:48:47 +02008341 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008342 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008343 ev->rssi = rssi;
8344
8345 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008346 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008347
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008348 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008349
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008350 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008351}
Johan Hedberg314b2382011-04-27 10:29:57 -04008352
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008353void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008354{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008355 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008356
Andre Guedes343fb142011-11-22 17:14:19 -03008357 BT_DBG("%s discovering %u", hdev->name, discovering);
8358
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008359 memset(&ev, 0, sizeof(ev));
8360 ev.type = hdev->discovery.type;
8361 ev.discovering = discovering;
8362
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008363 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008364}
Antti Julku5e762442011-08-25 16:48:02 +03008365
Marcel Holtmann1904a852015-01-11 13:50:44 -08008366static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008367{
8368 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008369}
8370
8371void mgmt_reenable_advertising(struct hci_dev *hdev)
8372{
8373 struct hci_request req;
8374
Arman Uguray24b4f382015-03-23 15:57:12 -07008375 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8376 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008377 return;
8378
8379 hci_req_init(&req, hdev);
8380 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008381 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008382}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008383
8384static struct hci_mgmt_chan chan = {
8385 .channel = HCI_CHANNEL_CONTROL,
8386 .handler_count = ARRAY_SIZE(mgmt_handlers),
8387 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008388 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008389};
8390
8391int mgmt_init(void)
8392{
8393 return hci_mgmt_chan_register(&chan);
8394}
8395
8396void mgmt_exit(void)
8397{
8398 hci_mgmt_chan_unregister(&chan);
8399}