blob: 58d60cbbc33f89e310681c666a0d480eebbc9d4f [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg71290692015-02-20 13:26:23 +020032#include <net/bluetooth/hci_sock.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030033#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020034#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070035
Johan Hedberg0857dd32014-12-19 13:40:20 +020036#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070037#include "smp.h"
Johan Hedberga380b6c2015-03-17 13:48:48 +020038#include "mgmt_util.h"
Johan Hedberg03811012010-12-08 00:21:06 +020039
Johan Hedberg2da9c552012-02-17 14:39:28 +020040#define MGMT_VERSION 1
Marcel Holtmannbeb1c212015-03-10 14:04:52 -070041#define MGMT_REVISION 9
Johan Hedberg02d98122010-12-13 21:07:04 +020042
Johan Hedberge70bb2e2012-02-13 16:59:33 +020043static const u16 mgmt_commands[] = {
44 MGMT_OP_READ_INDEX_LIST,
45 MGMT_OP_READ_INFO,
46 MGMT_OP_SET_POWERED,
47 MGMT_OP_SET_DISCOVERABLE,
48 MGMT_OP_SET_CONNECTABLE,
49 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030050 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020051 MGMT_OP_SET_LINK_SECURITY,
52 MGMT_OP_SET_SSP,
53 MGMT_OP_SET_HS,
54 MGMT_OP_SET_LE,
55 MGMT_OP_SET_DEV_CLASS,
56 MGMT_OP_SET_LOCAL_NAME,
57 MGMT_OP_ADD_UUID,
58 MGMT_OP_REMOVE_UUID,
59 MGMT_OP_LOAD_LINK_KEYS,
60 MGMT_OP_LOAD_LONG_TERM_KEYS,
61 MGMT_OP_DISCONNECT,
62 MGMT_OP_GET_CONNECTIONS,
63 MGMT_OP_PIN_CODE_REPLY,
64 MGMT_OP_PIN_CODE_NEG_REPLY,
65 MGMT_OP_SET_IO_CAPABILITY,
66 MGMT_OP_PAIR_DEVICE,
67 MGMT_OP_CANCEL_PAIR_DEVICE,
68 MGMT_OP_UNPAIR_DEVICE,
69 MGMT_OP_USER_CONFIRM_REPLY,
70 MGMT_OP_USER_CONFIRM_NEG_REPLY,
71 MGMT_OP_USER_PASSKEY_REPLY,
72 MGMT_OP_USER_PASSKEY_NEG_REPLY,
73 MGMT_OP_READ_LOCAL_OOB_DATA,
74 MGMT_OP_ADD_REMOTE_OOB_DATA,
75 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
76 MGMT_OP_START_DISCOVERY,
77 MGMT_OP_STOP_DISCOVERY,
78 MGMT_OP_CONFIRM_NAME,
79 MGMT_OP_BLOCK_DEVICE,
80 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070081 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030082 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030083 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070084 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070085 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080086 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080087 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020088 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020089 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020090 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030091 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020092 MGMT_OP_ADD_DEVICE,
93 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030094 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020095 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020096 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020097 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020098 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010099 MGMT_OP_START_SERVICE_DISCOVERY,
Marcel Holtmann4f0f1552015-03-14 22:43:19 -0700100 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann96f14742015-03-14 19:27:57 -0700101 MGMT_OP_READ_EXT_INDEX_LIST,
Marcel Holtmannd3d53052015-03-14 20:53:25 -0700102 MGMT_OP_READ_ADV_FEATURES,
Arman Uguray24b4f382015-03-23 15:57:12 -0700103 MGMT_OP_ADD_ADVERTISING,
Arman Ugurayda9293352015-03-23 15:57:13 -0700104 MGMT_OP_REMOVE_ADVERTISING,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200105};
106
107static const u16 mgmt_events[] = {
108 MGMT_EV_CONTROLLER_ERROR,
109 MGMT_EV_INDEX_ADDED,
110 MGMT_EV_INDEX_REMOVED,
111 MGMT_EV_NEW_SETTINGS,
112 MGMT_EV_CLASS_OF_DEV_CHANGED,
113 MGMT_EV_LOCAL_NAME_CHANGED,
114 MGMT_EV_NEW_LINK_KEY,
115 MGMT_EV_NEW_LONG_TERM_KEY,
116 MGMT_EV_DEVICE_CONNECTED,
117 MGMT_EV_DEVICE_DISCONNECTED,
118 MGMT_EV_CONNECT_FAILED,
119 MGMT_EV_PIN_CODE_REQUEST,
120 MGMT_EV_USER_CONFIRM_REQUEST,
121 MGMT_EV_USER_PASSKEY_REQUEST,
122 MGMT_EV_AUTH_FAILED,
123 MGMT_EV_DEVICE_FOUND,
124 MGMT_EV_DISCOVERING,
125 MGMT_EV_DEVICE_BLOCKED,
126 MGMT_EV_DEVICE_UNBLOCKED,
127 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300128 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800129 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700130 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200131 MGMT_EV_DEVICE_ADDED,
132 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300133 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200134 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200135 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200136 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700137 MGMT_EV_EXT_INDEX_ADDED,
138 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700139 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Arman Uguray24b4f382015-03-23 15:57:12 -0700140 MGMT_EV_ADVERTISING_ADDED,
141 MGMT_EV_ADVERTISING_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200142};
143
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700144static const u16 mgmt_untrusted_commands[] = {
145 MGMT_OP_READ_INDEX_LIST,
146 MGMT_OP_READ_INFO,
147 MGMT_OP_READ_UNCONF_INDEX_LIST,
148 MGMT_OP_READ_CONFIG_INFO,
149 MGMT_OP_READ_EXT_INDEX_LIST,
150};
151
152static const u16 mgmt_untrusted_events[] = {
153 MGMT_EV_INDEX_ADDED,
154 MGMT_EV_INDEX_REMOVED,
155 MGMT_EV_NEW_SETTINGS,
156 MGMT_EV_CLASS_OF_DEV_CHANGED,
157 MGMT_EV_LOCAL_NAME_CHANGED,
158 MGMT_EV_UNCONF_INDEX_ADDED,
159 MGMT_EV_UNCONF_INDEX_REMOVED,
160 MGMT_EV_NEW_CONFIG_OPTIONS,
161 MGMT_EV_EXT_INDEX_ADDED,
162 MGMT_EV_EXT_INDEX_REMOVED,
163};
164
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800165#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200166
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200167#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
168 "\x00\x00\x00\x00\x00\x00\x00\x00"
169
Johan Hedbergca69b792011-11-11 18:10:00 +0200170/* HCI to MGMT error code conversion table */
171static u8 mgmt_status_table[] = {
172 MGMT_STATUS_SUCCESS,
173 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
174 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
175 MGMT_STATUS_FAILED, /* Hardware Failure */
176 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
177 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200178 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200179 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
180 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
181 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
182 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
183 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
184 MGMT_STATUS_BUSY, /* Command Disallowed */
185 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
186 MGMT_STATUS_REJECTED, /* Rejected Security */
187 MGMT_STATUS_REJECTED, /* Rejected Personal */
188 MGMT_STATUS_TIMEOUT, /* Host Timeout */
189 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
190 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
191 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
192 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
193 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
194 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
195 MGMT_STATUS_BUSY, /* Repeated Attempts */
196 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
197 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
198 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
199 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
200 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
201 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
202 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
203 MGMT_STATUS_FAILED, /* Unspecified Error */
204 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
205 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
206 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
207 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
208 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
209 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
210 MGMT_STATUS_FAILED, /* Unit Link Key Used */
211 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
212 MGMT_STATUS_TIMEOUT, /* Instant Passed */
213 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
214 MGMT_STATUS_FAILED, /* Transaction Collision */
215 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
216 MGMT_STATUS_REJECTED, /* QoS Rejected */
217 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
218 MGMT_STATUS_REJECTED, /* Insufficient Security */
219 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
220 MGMT_STATUS_BUSY, /* Role Switch Pending */
221 MGMT_STATUS_FAILED, /* Slot Violation */
222 MGMT_STATUS_FAILED, /* Role Switch Failed */
223 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
224 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
225 MGMT_STATUS_BUSY, /* Host Busy Pairing */
226 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
227 MGMT_STATUS_BUSY, /* Controller Busy */
228 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
229 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
230 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
231 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
232 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
233};
234
235static u8 mgmt_status(u8 hci_status)
236{
237 if (hci_status < ARRAY_SIZE(mgmt_status_table))
238 return mgmt_status_table[hci_status];
239
240 return MGMT_STATUS_FAILED;
241}
242
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700243static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
244 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700245{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700246 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
247 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700248}
249
Marcel Holtmann72000df2015-03-16 16:11:21 -0700250static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
251 u16 len, int flag, struct sock *skip_sk)
252{
253 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
254 flag, skip_sk);
255}
256
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700257static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
258 u16 len, struct sock *skip_sk)
259{
260 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
261 HCI_MGMT_GENERIC_EVENTS, skip_sk);
262}
263
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200264static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
265 struct sock *skip_sk)
266{
267 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700268 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200269}
270
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300271static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
272 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200273{
274 struct mgmt_rp_read_version rp;
275
276 BT_DBG("sock %p", sk);
277
278 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700279 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200280
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200281 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
282 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200283}
284
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300285static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
286 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200287{
288 struct mgmt_rp_read_commands *rp;
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700289 u16 num_commands, num_events;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200290 size_t rp_size;
291 int i, err;
292
293 BT_DBG("sock %p", sk);
294
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700295 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
296 num_commands = ARRAY_SIZE(mgmt_commands);
297 num_events = ARRAY_SIZE(mgmt_events);
298 } else {
299 num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
300 num_events = ARRAY_SIZE(mgmt_untrusted_events);
301 }
302
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200303 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
304
305 rp = kmalloc(rp_size, GFP_KERNEL);
306 if (!rp)
307 return -ENOMEM;
308
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700309 rp->num_commands = cpu_to_le16(num_commands);
310 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700312 if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
313 __le16 *opcode = rp->opcodes;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200314
Marcel Holtmann99c679a2015-03-24 17:31:03 -0700315 for (i = 0; i < num_commands; i++, opcode++)
316 put_unaligned_le16(mgmt_commands[i], opcode);
317
318 for (i = 0; i < num_events; i++, opcode++)
319 put_unaligned_le16(mgmt_events[i], opcode);
320 } else {
321 __le16 *opcode = rp->opcodes;
322
323 for (i = 0; i < num_commands; i++, opcode++)
324 put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
325
326 for (i = 0; i < num_events; i++, opcode++)
327 put_unaligned_le16(mgmt_untrusted_events[i], opcode);
328 }
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200329
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200330 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
331 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 kfree(rp);
333
334 return err;
335}
336
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300337static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
338 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200341 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200342 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200343 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300344 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345
346 BT_DBG("sock %p", sk);
347
348 read_lock(&hci_dev_list_lock);
349
350 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300351 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200352 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700353 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700354 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200355 }
356
Johan Hedberga38528f2011-01-22 06:46:43 +0200357 rp_len = sizeof(*rp) + (2 * count);
358 rp = kmalloc(rp_len, GFP_ATOMIC);
359 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100360 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100362 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363
Johan Hedberg476e44c2012-10-19 20:10:46 +0300364 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200365 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700366 if (hci_dev_test_flag(d, HCI_SETUP) ||
367 hci_dev_test_flag(d, HCI_CONFIG) ||
368 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200369 continue;
370
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200371 /* Devices marked as raw-only are neither configured
372 * nor unconfigured controllers.
373 */
374 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700375 continue;
376
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200377 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700378 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700379 rp->index[count++] = cpu_to_le16(d->id);
380 BT_DBG("Added hci%u", d->id);
381 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 }
383
Johan Hedberg476e44c2012-10-19 20:10:46 +0300384 rp->num_controllers = cpu_to_le16(count);
385 rp_len = sizeof(*rp) + (2 * count);
386
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200387 read_unlock(&hci_dev_list_lock);
388
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200389 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
390 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200391
Johan Hedberga38528f2011-01-22 06:46:43 +0200392 kfree(rp);
393
394 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200395}
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
398 void *data, u16 data_len)
399{
400 struct mgmt_rp_read_unconf_index_list *rp;
401 struct hci_dev *d;
402 size_t rp_len;
403 u16 count;
404 int err;
405
406 BT_DBG("sock %p", sk);
407
408 read_lock(&hci_dev_list_lock);
409
410 count = 0;
411 list_for_each_entry(d, &hci_dev_list, list) {
412 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700413 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200414 count++;
415 }
416
417 rp_len = sizeof(*rp) + (2 * count);
418 rp = kmalloc(rp_len, GFP_ATOMIC);
419 if (!rp) {
420 read_unlock(&hci_dev_list_lock);
421 return -ENOMEM;
422 }
423
424 count = 0;
425 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700426 if (hci_dev_test_flag(d, HCI_SETUP) ||
427 hci_dev_test_flag(d, HCI_CONFIG) ||
428 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200429 continue;
430
431 /* Devices marked as raw-only are neither configured
432 * nor unconfigured controllers.
433 */
434 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
435 continue;
436
437 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700438 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200439 rp->index[count++] = cpu_to_le16(d->id);
440 BT_DBG("Added hci%u", d->id);
441 }
442 }
443
444 rp->num_controllers = cpu_to_le16(count);
445 rp_len = sizeof(*rp) + (2 * count);
446
447 read_unlock(&hci_dev_list_lock);
448
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200449 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
450 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200451
452 kfree(rp);
453
454 return err;
455}
456
Marcel Holtmann96f14742015-03-14 19:27:57 -0700457static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
458 void *data, u16 data_len)
459{
460 struct mgmt_rp_read_ext_index_list *rp;
461 struct hci_dev *d;
462 size_t rp_len;
463 u16 count;
464 int err;
465
466 BT_DBG("sock %p", sk);
467
468 read_lock(&hci_dev_list_lock);
469
470 count = 0;
471 list_for_each_entry(d, &hci_dev_list, list) {
472 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
473 count++;
474 }
475
476 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
477 rp = kmalloc(rp_len, GFP_ATOMIC);
478 if (!rp) {
479 read_unlock(&hci_dev_list_lock);
480 return -ENOMEM;
481 }
482
483 count = 0;
484 list_for_each_entry(d, &hci_dev_list, list) {
485 if (hci_dev_test_flag(d, HCI_SETUP) ||
486 hci_dev_test_flag(d, HCI_CONFIG) ||
487 hci_dev_test_flag(d, HCI_USER_CHANNEL))
488 continue;
489
490 /* Devices marked as raw-only are neither configured
491 * nor unconfigured controllers.
492 */
493 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
494 continue;
495
496 if (d->dev_type == HCI_BREDR) {
497 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
498 rp->entry[count].type = 0x01;
499 else
500 rp->entry[count].type = 0x00;
501 } else if (d->dev_type == HCI_AMP) {
502 rp->entry[count].type = 0x02;
503 } else {
504 continue;
505 }
506
507 rp->entry[count].bus = d->bus;
508 rp->entry[count++].index = cpu_to_le16(d->id);
509 BT_DBG("Added hci%u", d->id);
510 }
511
512 rp->num_controllers = cpu_to_le16(count);
513 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
514
515 read_unlock(&hci_dev_list_lock);
516
517 /* If this command is called at least once, then all the
518 * default index and unconfigured index events are disabled
519 * and from now on only extended index events are used.
520 */
521 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
522 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
523 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
524
525 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
526 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
527
528 kfree(rp);
529
530 return err;
531}
532
Marcel Holtmanndbece372014-07-04 18:11:55 +0200533static bool is_configured(struct hci_dev *hdev)
534{
535 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700536 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200537 return false;
538
539 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
540 !bacmp(&hdev->public_addr, BDADDR_ANY))
541 return false;
542
543 return true;
544}
545
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200546static __le32 get_missing_options(struct hci_dev *hdev)
547{
548 u32 options = 0;
549
Marcel Holtmanndbece372014-07-04 18:11:55 +0200550 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700551 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200552 options |= MGMT_OPTION_EXTERNAL_CONFIG;
553
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200554 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
555 !bacmp(&hdev->public_addr, BDADDR_ANY))
556 options |= MGMT_OPTION_PUBLIC_ADDRESS;
557
558 return cpu_to_le32(options);
559}
560
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200561static int new_options(struct hci_dev *hdev, struct sock *skip)
562{
563 __le32 options = get_missing_options(hdev);
564
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700565 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
566 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200567}
568
Marcel Holtmanndbece372014-07-04 18:11:55 +0200569static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
570{
571 __le32 options = get_missing_options(hdev);
572
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200573 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
574 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200575}
576
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200577static int read_config_info(struct sock *sk, struct hci_dev *hdev,
578 void *data, u16 data_len)
579{
580 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200581 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200582
583 BT_DBG("sock %p %s", sk, hdev->name);
584
585 hci_dev_lock(hdev);
586
587 memset(&rp, 0, sizeof(rp));
588 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200589
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200590 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
591 options |= MGMT_OPTION_EXTERNAL_CONFIG;
592
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200593 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200594 options |= MGMT_OPTION_PUBLIC_ADDRESS;
595
596 rp.supported_options = cpu_to_le32(options);
597 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200598
599 hci_dev_unlock(hdev);
600
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200601 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
602 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200603}
604
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200606{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200608
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300610 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800611 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300612 settings |= MGMT_SETTING_CONNECTABLE;
613 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200614
Andre Guedesed3fa312012-07-24 15:03:46 -0300615 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500616 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
617 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_BREDR;
619 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700620
621 if (lmp_ssp_capable(hdev)) {
622 settings |= MGMT_SETTING_SSP;
623 settings |= MGMT_SETTING_HS;
624 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800625
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800626 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700628 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100629
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300630 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200631 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300632 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300633 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800635 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300636 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200637
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200638 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
639 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200640 settings |= MGMT_SETTING_CONFIGURATION;
641
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200642 return settings;
643}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200644
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200645static u32 get_current_settings(struct hci_dev *hdev)
646{
647 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200648
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200649 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100650 settings |= MGMT_SETTING_POWERED;
651
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700652 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200653 settings |= MGMT_SETTING_CONNECTABLE;
654
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700655 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500656 settings |= MGMT_SETTING_FAST_CONNECTABLE;
657
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700658 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200659 settings |= MGMT_SETTING_DISCOVERABLE;
660
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700661 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300662 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200663
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700664 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200665 settings |= MGMT_SETTING_BREDR;
666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700667 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200668 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700670 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200672
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700673 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200674 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200675
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700676 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200677 settings |= MGMT_SETTING_HS;
678
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700679 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300680 settings |= MGMT_SETTING_ADVERTISING;
681
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700682 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800683 settings |= MGMT_SETTING_SECURE_CONN;
684
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700685 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800686 settings |= MGMT_SETTING_DEBUG_KEYS;
687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700688 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200689 settings |= MGMT_SETTING_PRIVACY;
690
Marcel Holtmann93690c22015-03-06 10:11:21 -0800691 /* The current setting for static address has two purposes. The
692 * first is to indicate if the static address will be used and
693 * the second is to indicate if it is actually set.
694 *
695 * This means if the static address is not configured, this flag
Marcel Holtmann08dc0e92015-03-25 18:32:13 -0700696 * will never be set. If the address is configured, then if the
Marcel Holtmann93690c22015-03-06 10:11:21 -0800697 * address is actually used decides if the flag is set or not.
698 *
699 * For single mode LE only controllers and dual-mode controllers
700 * with BR/EDR disabled, the existence of the static address will
701 * be evaluated.
702 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700703 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700704 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800705 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
706 if (bacmp(&hdev->static_addr, BDADDR_ANY))
707 settings |= MGMT_SETTING_STATIC_ADDRESS;
708 }
709
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200710 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200711}
712
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300713#define PNP_INFO_SVCLASS_ID 0x1200
714
Johan Hedberg213202e2013-01-27 00:31:33 +0200715static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
716{
717 u8 *ptr = data, *uuids_start = NULL;
718 struct bt_uuid *uuid;
719
720 if (len < 4)
721 return ptr;
722
723 list_for_each_entry(uuid, &hdev->uuids, list) {
724 u16 uuid16;
725
726 if (uuid->size != 16)
727 continue;
728
729 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
730 if (uuid16 < 0x1100)
731 continue;
732
733 if (uuid16 == PNP_INFO_SVCLASS_ID)
734 continue;
735
736 if (!uuids_start) {
737 uuids_start = ptr;
738 uuids_start[0] = 1;
739 uuids_start[1] = EIR_UUID16_ALL;
740 ptr += 2;
741 }
742
743 /* Stop if not enough space to put next UUID */
744 if ((ptr - data) + sizeof(u16) > len) {
745 uuids_start[1] = EIR_UUID16_SOME;
746 break;
747 }
748
749 *ptr++ = (uuid16 & 0x00ff);
750 *ptr++ = (uuid16 & 0xff00) >> 8;
751 uuids_start[0] += sizeof(uuid16);
752 }
753
754 return ptr;
755}
756
Johan Hedbergcdf19632013-01-27 00:31:34 +0200757static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
758{
759 u8 *ptr = data, *uuids_start = NULL;
760 struct bt_uuid *uuid;
761
762 if (len < 6)
763 return ptr;
764
765 list_for_each_entry(uuid, &hdev->uuids, list) {
766 if (uuid->size != 32)
767 continue;
768
769 if (!uuids_start) {
770 uuids_start = ptr;
771 uuids_start[0] = 1;
772 uuids_start[1] = EIR_UUID32_ALL;
773 ptr += 2;
774 }
775
776 /* Stop if not enough space to put next UUID */
777 if ((ptr - data) + sizeof(u32) > len) {
778 uuids_start[1] = EIR_UUID32_SOME;
779 break;
780 }
781
782 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
783 ptr += sizeof(u32);
784 uuids_start[0] += sizeof(u32);
785 }
786
787 return ptr;
788}
789
Johan Hedbergc00d5752013-01-27 00:31:35 +0200790static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
791{
792 u8 *ptr = data, *uuids_start = NULL;
793 struct bt_uuid *uuid;
794
795 if (len < 18)
796 return ptr;
797
798 list_for_each_entry(uuid, &hdev->uuids, list) {
799 if (uuid->size != 128)
800 continue;
801
802 if (!uuids_start) {
803 uuids_start = ptr;
804 uuids_start[0] = 1;
805 uuids_start[1] = EIR_UUID128_ALL;
806 ptr += 2;
807 }
808
809 /* Stop if not enough space to put next UUID */
810 if ((ptr - data) + 16 > len) {
811 uuids_start[1] = EIR_UUID128_SOME;
812 break;
813 }
814
815 memcpy(ptr, uuid->uuid, 16);
816 ptr += 16;
817 uuids_start[0] += 16;
818 }
819
820 return ptr;
821}
822
Johan Hedberg333ae952015-03-17 13:48:47 +0200823static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
824{
825 return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
826}
827
Johan Hedberg333ae952015-03-17 13:48:47 +0200828static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
829 struct hci_dev *hdev,
830 const void *data)
831{
832 return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
833}
834
Arman Uguray4117ed72015-03-23 15:57:14 -0700835static u8 create_default_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700836{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700837 u8 ad_len = 0;
838 size_t name_len;
839
840 name_len = strlen(hdev->dev_name);
841 if (name_len > 0) {
842 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
843
844 if (name_len > max_len) {
845 name_len = max_len;
846 ptr[1] = EIR_NAME_SHORT;
847 } else
848 ptr[1] = EIR_NAME_COMPLETE;
849
850 ptr[0] = name_len + 1;
851
852 memcpy(ptr + 2, hdev->dev_name, name_len);
853
854 ad_len += (name_len + 2);
855 ptr += (name_len + 2);
856 }
857
858 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700859}
860
Arman Uguray4117ed72015-03-23 15:57:14 -0700861static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
862{
863 /* TODO: Set the appropriate entries based on advertising instance flags
864 * here once flags other than 0 are supported.
865 */
866 memcpy(ptr, hdev->adv_instance.scan_rsp_data,
867 hdev->adv_instance.scan_rsp_len);
868
869 return hdev->adv_instance.scan_rsp_len;
870}
871
872static void update_scan_rsp_data_for_instance(struct hci_request *req,
873 u8 instance)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700874{
875 struct hci_dev *hdev = req->hdev;
876 struct hci_cp_le_set_scan_rsp_data cp;
877 u8 len;
878
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700880 return;
881
882 memset(&cp, 0, sizeof(cp));
883
Arman Uguray4117ed72015-03-23 15:57:14 -0700884 if (instance)
885 len = create_instance_scan_rsp_data(hdev, cp.data);
886 else
887 len = create_default_scan_rsp_data(hdev, cp.data);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700888
Johan Hedbergeb438b52013-10-16 15:31:07 +0300889 if (hdev->scan_rsp_data_len == len &&
Arman Uguray4117ed72015-03-23 15:57:14 -0700890 !memcmp(cp.data, hdev->scan_rsp_data, len))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700891 return;
892
Johan Hedbergeb438b52013-10-16 15:31:07 +0300893 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
894 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700895
896 cp.length = len;
897
898 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
899}
900
Arman Uguray4117ed72015-03-23 15:57:14 -0700901static void update_scan_rsp_data(struct hci_request *req)
902{
903 struct hci_dev *hdev = req->hdev;
904 u8 instance;
905
906 /* The "Set Advertising" setting supersedes the "Add Advertising"
907 * setting. Here we set the scan response data based on which
908 * setting was set. When neither apply, default to the global settings,
909 * represented by instance "0".
910 */
911 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
912 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
913 instance = 0x01;
914 else
915 instance = 0x00;
916
917 update_scan_rsp_data_for_instance(req, instance);
918}
919
Johan Hedberg9a43e252013-10-20 19:00:07 +0300920static u8 get_adv_discov_flags(struct hci_dev *hdev)
921{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200922 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300923
924 /* If there's a pending mgmt command the flags will not yet have
925 * their final values, so check for this first.
926 */
Johan Hedberg333ae952015-03-17 13:48:47 +0200927 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg9a43e252013-10-20 19:00:07 +0300928 if (cmd) {
929 struct mgmt_mode *cp = cmd->param;
930 if (cp->val == 0x01)
931 return LE_AD_GENERAL;
932 else if (cp->val == 0x02)
933 return LE_AD_LIMITED;
934 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700935 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300936 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700937 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300938 return LE_AD_GENERAL;
939 }
940
941 return 0;
942}
943
Arman Uguraye7a685d2015-03-25 18:53:40 -0700944static u8 get_current_adv_instance(struct hci_dev *hdev)
Arman Uguray24b4f382015-03-23 15:57:12 -0700945{
Arman Uguray24b4f382015-03-23 15:57:12 -0700946 /* The "Set Advertising" setting supersedes the "Add Advertising"
947 * setting. Here we set the advertising data based on which
948 * setting was set. When neither apply, default to the global settings,
949 * represented by instance "0".
950 */
951 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
952 !hci_dev_test_flag(hdev, HCI_ADVERTISING))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700953 return 0x01;
954
955 return 0x00;
956}
957
958static bool get_connectable(struct hci_dev *hdev)
959{
960 struct mgmt_pending_cmd *cmd;
961
962 /* If there's a pending mgmt command the flag will not yet have
963 * it's final value, so check for this first.
964 */
965 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
966 if (cmd) {
967 struct mgmt_mode *cp = cmd->param;
968
969 return cp->val;
970 }
971
972 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
973}
974
975static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
976{
977 u32 flags;
978
979 if (instance > 0x01)
980 return 0;
981
Arman Ugurayfdf51782015-03-25 18:53:46 -0700982 if (instance == 0x01)
Arman Uguraye7a685d2015-03-25 18:53:40 -0700983 return hdev->adv_instance.flags;
984
Arman Ugurayfdf51782015-03-25 18:53:46 -0700985 /* Instance 0 always manages the "Tx Power" and "Flags" fields */
986 flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguraye7a685d2015-03-25 18:53:40 -0700987
Arman Ugurayfaccb952015-03-28 12:38:58 -0700988 /* For instance 0, the HCI_ADVERTISING_CONNECTABLE setting corresponds
989 * to the "connectable" instance flag.
990 */
991 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Arman Uguraye7a685d2015-03-25 18:53:40 -0700992 flags |= MGMT_ADV_FLAG_CONNECTABLE;
993
Arman Uguraye7a685d2015-03-25 18:53:40 -0700994 return flags;
995}
996
Arman Ugurayc7d48832015-03-28 12:38:59 -0700997static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
998{
999 /* Ignore instance 0 and other unsupported instances */
1000 if (instance != 0x01)
1001 return 0;
1002
1003 /* TODO: Take into account the "appearance" and "local-name" flags here.
1004 * These are currently being ignored as they are not supported.
1005 */
1006 return hdev->adv_instance.scan_rsp_len;
1007}
1008
Arman Ugurayfdf51782015-03-25 18:53:46 -07001009static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1010{
1011 u8 ad_len = 0, flags = 0;
1012 u32 instance_flags = get_adv_instance_flags(hdev, instance);
1013
1014 /* The Add Advertising command allows userspace to set both the general
1015 * and limited discoverable flags.
1016 */
1017 if (instance_flags & MGMT_ADV_FLAG_DISCOV)
1018 flags |= LE_AD_GENERAL;
1019
1020 if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
1021 flags |= LE_AD_LIMITED;
1022
1023 if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
1024 /* If a discovery flag wasn't provided, simply use the global
1025 * settings.
1026 */
1027 if (!flags)
1028 flags |= get_adv_discov_flags(hdev);
1029
1030 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
1031 flags |= LE_AD_NO_BREDR;
1032
1033 /* If flags would still be empty, then there is no need to
1034 * include the "Flags" AD field".
1035 */
1036 if (flags) {
1037 ptr[0] = 0x02;
1038 ptr[1] = EIR_FLAGS;
1039 ptr[2] = flags;
1040
1041 ad_len += 3;
1042 ptr += 3;
1043 }
1044 }
1045
Marcel Holtmann38c8af62015-04-03 13:23:12 -07001046 if (instance) {
1047 memcpy(ptr, hdev->adv_instance.adv_data,
1048 hdev->adv_instance.adv_data_len);
1049
1050 ad_len += hdev->adv_instance.adv_data_len;
1051 ptr += hdev->adv_instance.adv_data_len;
1052 }
1053
Arman Ugurayfdf51782015-03-25 18:53:46 -07001054 /* Provide Tx Power only if we can provide a valid value for it */
1055 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
1056 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1057 ptr[0] = 0x02;
1058 ptr[1] = EIR_TX_POWER;
1059 ptr[2] = (u8)hdev->adv_tx_power;
1060
1061 ad_len += 3;
1062 ptr += 3;
1063 }
1064
Arman Ugurayfdf51782015-03-25 18:53:46 -07001065 return ad_len;
1066}
1067
1068static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
1069{
1070 struct hci_dev *hdev = req->hdev;
1071 struct hci_cp_le_set_adv_data cp;
1072 u8 len;
1073
1074 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1075 return;
1076
1077 memset(&cp, 0, sizeof(cp));
1078
1079 len = create_instance_adv_data(hdev, instance, cp.data);
1080
1081 /* There's nothing to do if the data hasn't changed */
1082 if (hdev->adv_data_len == len &&
1083 memcmp(cp.data, hdev->adv_data, len) == 0)
1084 return;
1085
1086 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1087 hdev->adv_data_len = len;
1088
1089 cp.length = len;
1090
1091 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1092}
1093
Arman Uguraye7a685d2015-03-25 18:53:40 -07001094static void update_adv_data(struct hci_request *req)
1095{
1096 struct hci_dev *hdev = req->hdev;
1097 u8 instance = get_current_adv_instance(hdev);
Arman Uguray24b4f382015-03-23 15:57:12 -07001098
1099 update_adv_data_for_instance(req, instance);
1100}
1101
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001102int mgmt_update_adv_data(struct hci_dev *hdev)
1103{
1104 struct hci_request req;
1105
1106 hci_req_init(&req, hdev);
1107 update_adv_data(&req);
1108
1109 return hci_req_run(&req, NULL);
1110}
1111
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001112static void create_eir(struct hci_dev *hdev, u8 *data)
1113{
1114 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001115 size_t name_len;
1116
1117 name_len = strlen(hdev->dev_name);
1118
1119 if (name_len > 0) {
1120 /* EIR Data type */
1121 if (name_len > 48) {
1122 name_len = 48;
1123 ptr[1] = EIR_NAME_SHORT;
1124 } else
1125 ptr[1] = EIR_NAME_COMPLETE;
1126
1127 /* EIR Data length */
1128 ptr[0] = name_len + 1;
1129
1130 memcpy(ptr + 2, hdev->dev_name, name_len);
1131
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001132 ptr += (name_len + 2);
1133 }
1134
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001135 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001136 ptr[0] = 2;
1137 ptr[1] = EIR_TX_POWER;
1138 ptr[2] = (u8) hdev->inq_tx_power;
1139
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001140 ptr += 3;
1141 }
1142
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001143 if (hdev->devid_source > 0) {
1144 ptr[0] = 9;
1145 ptr[1] = EIR_DEVICE_ID;
1146
1147 put_unaligned_le16(hdev->devid_source, ptr + 2);
1148 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1149 put_unaligned_le16(hdev->devid_product, ptr + 6);
1150 put_unaligned_le16(hdev->devid_version, ptr + 8);
1151
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001152 ptr += 10;
1153 }
1154
Johan Hedberg213202e2013-01-27 00:31:33 +02001155 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001156 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001157 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001158}
1159
Johan Hedberg890ea892013-03-15 17:06:52 -05001160static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001161{
Johan Hedberg890ea892013-03-15 17:06:52 -05001162 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001163 struct hci_cp_write_eir cp;
1164
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001165 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001166 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001167
Johan Hedberg976eb202012-10-24 21:12:01 +03001168 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001169 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001170
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001171 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001172 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001173
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001174 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001175 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001176
1177 memset(&cp, 0, sizeof(cp));
1178
1179 create_eir(hdev, cp.data);
1180
1181 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001182 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001183
1184 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1185
Johan Hedberg890ea892013-03-15 17:06:52 -05001186 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001187}
1188
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001189static u8 get_service_classes(struct hci_dev *hdev)
1190{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001191 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001192 u8 val = 0;
1193
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001194 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001195 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001196
1197 return val;
1198}
1199
Johan Hedberg890ea892013-03-15 17:06:52 -05001200static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001201{
Johan Hedberg890ea892013-03-15 17:06:52 -05001202 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001203 u8 cod[3];
1204
1205 BT_DBG("%s", hdev->name);
1206
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001207 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001208 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001209
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001210 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001211 return;
1212
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001213 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001214 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001215
1216 cod[0] = hdev->minor_class;
1217 cod[1] = hdev->major_class;
1218 cod[2] = get_service_classes(hdev);
1219
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001220 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001221 cod[1] |= 0x20;
1222
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001223 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001224 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001225
Johan Hedberg890ea892013-03-15 17:06:52 -05001226 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001227}
1228
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001229static void disable_advertising(struct hci_request *req)
1230{
1231 u8 enable = 0x00;
1232
1233 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1234}
1235
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001236static void enable_advertising(struct hci_request *req)
1237{
1238 struct hci_dev *hdev = req->hdev;
1239 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001240 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001241 bool connectable;
Arman Uguraye7a685d2015-03-25 18:53:40 -07001242 u8 instance;
1243 u32 flags;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001244
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001245 if (hci_conn_num(hdev, LE_LINK) > 0)
1246 return;
1247
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001248 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001249 disable_advertising(req);
1250
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001251 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001252 * hci_update_random_address knows that it's safe to go ahead
1253 * and write a new random address. The flag will be set back on
1254 * as soon as the SET_ADV_ENABLE HCI command completes.
1255 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001256 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001257
Arman Uguraye7a685d2015-03-25 18:53:40 -07001258 instance = get_current_adv_instance(hdev);
1259 flags = get_adv_instance_flags(hdev, instance);
Arman Ugurayfaccb952015-03-28 12:38:58 -07001260
1261 /* If the "connectable" instance flag was not set, then choose between
1262 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1263 */
1264 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1265 get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001266
Johan Hedberga4858cb2014-02-25 19:56:31 +02001267 /* Set require_privacy to true only when non-connectable
1268 * advertising is used. In that case it is fine to use a
1269 * non-resolvable private address.
1270 */
1271 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001272 return;
1273
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001274 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001275 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1276 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Arman Ugurayc7d48832015-03-28 12:38:59 -07001277
1278 if (connectable)
1279 cp.type = LE_ADV_IND;
1280 else if (get_adv_instance_scan_rsp_len(hdev, instance))
1281 cp.type = LE_ADV_SCAN_IND;
1282 else
1283 cp.type = LE_ADV_NONCONN_IND;
1284
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001285 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001286 cp.channel_map = hdev->le_adv_channel_map;
1287
1288 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1289
1290 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1291}
1292
Johan Hedberg7d785252011-12-15 00:47:39 +02001293static void service_cache_off(struct work_struct *work)
1294{
1295 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001296 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001297 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001298
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001299 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001300 return;
1301
Johan Hedberg890ea892013-03-15 17:06:52 -05001302 hci_req_init(&req, hdev);
1303
Johan Hedberg7d785252011-12-15 00:47:39 +02001304 hci_dev_lock(hdev);
1305
Johan Hedberg890ea892013-03-15 17:06:52 -05001306 update_eir(&req);
1307 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001308
1309 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001310
1311 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001312}
1313
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001314static void rpa_expired(struct work_struct *work)
1315{
1316 struct hci_dev *hdev = container_of(work, struct hci_dev,
1317 rpa_expired.work);
1318 struct hci_request req;
1319
1320 BT_DBG("");
1321
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001322 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001323
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001324 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001325 return;
1326
1327 /* The generation of a new RPA and programming it into the
1328 * controller happens in the enable_advertising() function.
1329 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001330 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001331 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001332 hci_req_run(&req, NULL);
1333}
1334
Johan Hedberg6a919082012-02-28 06:17:26 +02001335static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001336{
Marcel Holtmann238be782015-03-13 02:11:06 -07001337 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001338 return;
1339
Johan Hedberg4f87da82012-03-02 19:55:56 +02001340 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001341 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001342
Johan Hedberg4f87da82012-03-02 19:55:56 +02001343 /* Non-mgmt controlled devices get this bit set
1344 * implicitly so that pairing works for them, however
1345 * for mgmt we require user-space to explicitly enable
1346 * it
1347 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001348 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001349}
1350
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001351static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001352 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001353{
1354 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001355
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001356 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001357
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001358 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001359
Johan Hedberg03811012010-12-08 00:21:06 +02001360 memset(&rp, 0, sizeof(rp));
1361
Johan Hedberg03811012010-12-08 00:21:06 +02001362 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001363
1364 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001365 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001366
1367 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1368 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1369
1370 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001371
1372 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001373 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001374
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001375 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001376
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001377 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1378 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001379}
1380
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001381static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001382{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001383 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001385 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1386 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001387}
1388
Marcel Holtmann1904a852015-01-11 13:50:44 -08001389static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001390{
1391 BT_DBG("%s status 0x%02x", hdev->name, status);
1392
Johan Hedberga3172b72014-02-28 09:33:44 +02001393 if (hci_conn_count(hdev) == 0) {
1394 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001395 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001396 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001397}
1398
Johan Hedberg23a48092014-07-08 16:05:06 +03001399static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001400{
1401 struct hci_dev *hdev = req->hdev;
1402 struct hci_cp_remote_name_req_cancel cp;
1403 struct inquiry_entry *e;
1404
1405 switch (hdev->discovery.state) {
1406 case DISCOVERY_FINDING:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001407 if (test_bit(HCI_INQUIRY, &hdev->flags))
Johan Hedberg21a60d32014-06-10 14:05:58 +03001408 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Jakub Pawlowski07d23342015-03-17 09:04:14 -07001409
1410 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001411 cancel_delayed_work(&hdev->le_scan_disable);
1412 hci_req_add_le_scan_disable(req);
1413 }
1414
Johan Hedberg23a48092014-07-08 16:05:06 +03001415 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001416
1417 case DISCOVERY_RESOLVING:
1418 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1419 NAME_PENDING);
1420 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001421 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001422
1423 bacpy(&cp.bdaddr, &e->data.bdaddr);
1424 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1425 &cp);
1426
Johan Hedberg23a48092014-07-08 16:05:06 +03001427 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001428
1429 default:
1430 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001431 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001432 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001433 return true;
1434 }
1435
Johan Hedberg21a60d32014-06-10 14:05:58 +03001436 break;
1437 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001438
1439 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001440}
1441
Arman Uguray912098a2015-03-23 15:57:15 -07001442static void advertising_added(struct sock *sk, struct hci_dev *hdev,
1443 u8 instance)
1444{
1445 struct mgmt_ev_advertising_added ev;
1446
1447 ev.instance = instance;
1448
1449 mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
1450}
1451
1452static void advertising_removed(struct sock *sk, struct hci_dev *hdev,
1453 u8 instance)
1454{
1455 struct mgmt_ev_advertising_removed ev;
1456
1457 ev.instance = instance;
1458
1459 mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
1460}
1461
1462static void clear_adv_instance(struct hci_dev *hdev)
1463{
1464 struct hci_request req;
1465
1466 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
1467 return;
1468
1469 if (hdev->adv_instance.timeout)
1470 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
1471
1472 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
1473 advertising_removed(NULL, hdev, 1);
1474 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
1475
1476 if (!hdev_is_powered(hdev) ||
1477 hci_dev_test_flag(hdev, HCI_ADVERTISING))
1478 return;
1479
1480 hci_req_init(&req, hdev);
1481 disable_advertising(&req);
1482 hci_req_run(&req, NULL);
1483}
1484
Johan Hedberg8b064a32014-02-24 14:52:22 +02001485static int clean_up_hci_state(struct hci_dev *hdev)
1486{
1487 struct hci_request req;
1488 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001489 bool discov_stopped;
1490 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001491
1492 hci_req_init(&req, hdev);
1493
1494 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1495 test_bit(HCI_PSCAN, &hdev->flags)) {
1496 u8 scan = 0x00;
1497 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1498 }
1499
Arman Uguray912098a2015-03-23 15:57:15 -07001500 if (hdev->adv_instance.timeout)
1501 clear_adv_instance(hdev);
1502
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001503 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001504 disable_advertising(&req);
1505
Johan Hedberg23a48092014-07-08 16:05:06 +03001506 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001507
1508 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1509 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001510 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001511
Johan Hedbergc9910d02014-02-27 14:35:12 +02001512 switch (conn->state) {
1513 case BT_CONNECTED:
1514 case BT_CONFIG:
1515 dc.handle = cpu_to_le16(conn->handle);
1516 dc.reason = 0x15; /* Terminated due to Power Off */
1517 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1518 break;
1519 case BT_CONNECT:
1520 if (conn->type == LE_LINK)
1521 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1522 0, NULL);
1523 else if (conn->type == ACL_LINK)
1524 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1525 6, &conn->dst);
1526 break;
1527 case BT_CONNECT2:
1528 bacpy(&rej.bdaddr, &conn->dst);
1529 rej.reason = 0x15; /* Terminated due to Power Off */
1530 if (conn->type == ACL_LINK)
1531 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1532 sizeof(rej), &rej);
1533 else if (conn->type == SCO_LINK)
1534 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1535 sizeof(rej), &rej);
1536 break;
1537 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001538 }
1539
Johan Hedberg23a48092014-07-08 16:05:06 +03001540 err = hci_req_run(&req, clean_up_hci_complete);
1541 if (!err && discov_stopped)
1542 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1543
1544 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001545}
1546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001547static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001548 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001549{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001550 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001551 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001552 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001554 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001555
Johan Hedberga7e80f22013-01-09 16:05:19 +02001556 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001557 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1558 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001559
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001560 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001561
Johan Hedberg333ae952015-03-17 13:48:47 +02001562 if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001563 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1564 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001565 goto failed;
1566 }
1567
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001568 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001569 cancel_delayed_work(&hdev->power_off);
1570
1571 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001572 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1573 data, len);
1574 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001575 goto failed;
1576 }
1577 }
1578
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001579 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001580 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001581 goto failed;
1582 }
1583
Johan Hedberg03811012010-12-08 00:21:06 +02001584 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1585 if (!cmd) {
1586 err = -ENOMEM;
1587 goto failed;
1588 }
1589
Johan Hedberg8b064a32014-02-24 14:52:22 +02001590 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001591 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001592 err = 0;
1593 } else {
1594 /* Disconnect connections, stop scans, etc */
1595 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001596 if (!err)
1597 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1598 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001599
Johan Hedberg8b064a32014-02-24 14:52:22 +02001600 /* ENODATA means there were no HCI commands queued */
1601 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001602 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001603 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1604 err = 0;
1605 }
1606 }
Johan Hedberg03811012010-12-08 00:21:06 +02001607
1608failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001609 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001610 return err;
1611}
1612
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001613static int new_settings(struct hci_dev *hdev, struct sock *skip)
1614{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001615 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001616
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001617 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1618 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001619}
1620
Johan Hedberg91a668b2014-07-09 13:28:26 +03001621int mgmt_new_settings(struct hci_dev *hdev)
1622{
1623 return new_settings(hdev, NULL);
1624}
1625
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001626struct cmd_lookup {
1627 struct sock *sk;
1628 struct hci_dev *hdev;
1629 u8 mgmt_status;
1630};
1631
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001632static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001633{
1634 struct cmd_lookup *match = data;
1635
1636 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1637
1638 list_del(&cmd->list);
1639
1640 if (match->sk == NULL) {
1641 match->sk = cmd->sk;
1642 sock_hold(match->sk);
1643 }
1644
1645 mgmt_pending_free(cmd);
1646}
1647
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001648static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001649{
1650 u8 *status = data;
1651
Johan Hedberga69e8372015-03-06 21:08:53 +02001652 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001653 mgmt_pending_remove(cmd);
1654}
1655
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001656static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001657{
1658 if (cmd->cmd_complete) {
1659 u8 *status = data;
1660
1661 cmd->cmd_complete(cmd, *status);
1662 mgmt_pending_remove(cmd);
1663
1664 return;
1665 }
1666
1667 cmd_status_rsp(cmd, data);
1668}
1669
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001670static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001671{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001672 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1673 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001674}
1675
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001676static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001677{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001678 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1679 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001680}
1681
Johan Hedberge6fe7982013-10-02 15:45:22 +03001682static u8 mgmt_bredr_support(struct hci_dev *hdev)
1683{
1684 if (!lmp_bredr_capable(hdev))
1685 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001686 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001687 return MGMT_STATUS_REJECTED;
1688 else
1689 return MGMT_STATUS_SUCCESS;
1690}
1691
1692static u8 mgmt_le_support(struct hci_dev *hdev)
1693{
1694 if (!lmp_le_capable(hdev))
1695 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001696 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001697 return MGMT_STATUS_REJECTED;
1698 else
1699 return MGMT_STATUS_SUCCESS;
1700}
1701
Marcel Holtmann1904a852015-01-11 13:50:44 -08001702static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1703 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001704{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001705 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001706 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001707 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001708 bool changed;
1709
1710 BT_DBG("status 0x%02x", status);
1711
1712 hci_dev_lock(hdev);
1713
Johan Hedberg333ae952015-03-17 13:48:47 +02001714 cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001715 if (!cmd)
1716 goto unlock;
1717
1718 if (status) {
1719 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001720 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001721 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001722 goto remove_cmd;
1723 }
1724
1725 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001726 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001727 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001728
1729 if (hdev->discov_timeout > 0) {
1730 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1731 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1732 to);
1733 }
1734 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001735 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001736 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737
1738 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1739
1740 if (changed)
1741 new_settings(hdev, cmd->sk);
1742
Marcel Holtmann970ba522013-10-15 06:33:57 -07001743 /* When the discoverable mode gets changed, make sure
1744 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001745 * bit correctly set. Also update page scan based on whitelist
1746 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001747 */
1748 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001749 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001750 update_class(&req);
1751 hci_req_run(&req, NULL);
1752
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001753remove_cmd:
1754 mgmt_pending_remove(cmd);
1755
1756unlock:
1757 hci_dev_unlock(hdev);
1758}
1759
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001760static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001761 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001762{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001763 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001764 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001765 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001766 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001767 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001768 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001769
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001770 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001771
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001772 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1773 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001774 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1775 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001776
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001777 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001778 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1779 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001780
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001781 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001782
1783 /* Disabling discoverable requires that no timeout is set,
1784 * and enabling limited discoverable requires a timeout.
1785 */
1786 if ((cp->val == 0x00 && timeout > 0) ||
1787 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001788 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1789 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001790
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001791 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001792
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001793 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001794 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1795 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001796 goto failed;
1797 }
1798
Johan Hedberg333ae952015-03-17 13:48:47 +02001799 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
1800 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001801 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1802 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001803 goto failed;
1804 }
1805
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001806 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001807 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1808 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001809 goto failed;
1810 }
1811
1812 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001813 bool changed = false;
1814
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001815 /* Setting limited discoverable when powered off is
1816 * not a valid operation since it requires a timeout
1817 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1818 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001819 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001820 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001821 changed = true;
1822 }
1823
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001824 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001825 if (err < 0)
1826 goto failed;
1827
1828 if (changed)
1829 err = new_settings(hdev, sk);
1830
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001831 goto failed;
1832 }
1833
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001834 /* If the current mode is the same, then just update the timeout
1835 * value with the new value. And if only the timeout gets updated,
1836 * then no need for any HCI transactions.
1837 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001838 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1839 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1840 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001841 cancel_delayed_work(&hdev->discov_off);
1842 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001843
Marcel Holtmann36261542013-10-15 08:28:51 -07001844 if (cp->val && hdev->discov_timeout > 0) {
1845 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001846 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001847 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001848 }
1849
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001850 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001851 goto failed;
1852 }
1853
1854 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1855 if (!cmd) {
1856 err = -ENOMEM;
1857 goto failed;
1858 }
1859
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001860 /* Cancel any potential discoverable timeout that might be
1861 * still active and store new timeout value. The arming of
1862 * the timeout happens in the complete handler.
1863 */
1864 cancel_delayed_work(&hdev->discov_off);
1865 hdev->discov_timeout = timeout;
1866
Johan Hedbergb456f872013-10-19 23:38:22 +03001867 /* Limited discoverable mode */
1868 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001869 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001870 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001871 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001872
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001873 hci_req_init(&req, hdev);
1874
Johan Hedberg9a43e252013-10-20 19:00:07 +03001875 /* The procedure for LE-only controllers is much simpler - just
1876 * update the advertising data.
1877 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001878 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001879 goto update_ad;
1880
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001881 scan = SCAN_PAGE;
1882
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001883 if (cp->val) {
1884 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001885
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001886 if (cp->val == 0x02) {
1887 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001888 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001889 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1890 hci_cp.iac_lap[1] = 0x8b;
1891 hci_cp.iac_lap[2] = 0x9e;
1892 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1893 hci_cp.iac_lap[4] = 0x8b;
1894 hci_cp.iac_lap[5] = 0x9e;
1895 } else {
1896 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001897 hci_cp.num_iac = 1;
1898 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1899 hci_cp.iac_lap[1] = 0x8b;
1900 hci_cp.iac_lap[2] = 0x9e;
1901 }
1902
1903 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1904 (hci_cp.num_iac * 3) + 1, &hci_cp);
1905
1906 scan |= SCAN_INQUIRY;
1907 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001908 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001909 }
1910
1911 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001912
Johan Hedberg9a43e252013-10-20 19:00:07 +03001913update_ad:
1914 update_adv_data(&req);
1915
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001916 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001917 if (err < 0)
1918 mgmt_pending_remove(cmd);
1919
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001920failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001921 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001922 return err;
1923}
1924
Johan Hedberg406d7802013-03-15 17:07:09 -05001925static void write_fast_connectable(struct hci_request *req, bool enable)
1926{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001927 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001928 struct hci_cp_write_page_scan_activity acp;
1929 u8 type;
1930
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001931 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001932 return;
1933
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001934 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1935 return;
1936
Johan Hedberg406d7802013-03-15 17:07:09 -05001937 if (enable) {
1938 type = PAGE_SCAN_TYPE_INTERLACED;
1939
1940 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001941 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001942 } else {
1943 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1944
1945 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001946 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001947 }
1948
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001949 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001950
Johan Hedbergbd98b992013-03-15 17:07:13 -05001951 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1952 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1953 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1954 sizeof(acp), &acp);
1955
1956 if (hdev->page_scan_type != type)
1957 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001958}
1959
Marcel Holtmann1904a852015-01-11 13:50:44 -08001960static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1961 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001962{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001963 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001964 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001965 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001966
1967 BT_DBG("status 0x%02x", status);
1968
1969 hci_dev_lock(hdev);
1970
Johan Hedberg333ae952015-03-17 13:48:47 +02001971 cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
Johan Hedberg2b76f452013-03-15 17:07:04 -05001972 if (!cmd)
1973 goto unlock;
1974
Johan Hedberg37438c12013-10-14 16:20:05 +03001975 if (status) {
1976 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001977 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001978 goto remove_cmd;
1979 }
1980
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001981 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001982 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001983 conn_changed = !hci_dev_test_and_set_flag(hdev,
1984 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001985 discov_changed = false;
1986 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001987 conn_changed = hci_dev_test_and_clear_flag(hdev,
1988 HCI_CONNECTABLE);
1989 discov_changed = hci_dev_test_and_clear_flag(hdev,
1990 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001991 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001992
Johan Hedberg2b76f452013-03-15 17:07:04 -05001993 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1994
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001995 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001996 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001997 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001998 if (discov_changed)
1999 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03002000 hci_update_background_scan(hdev);
2001 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03002002
Johan Hedberg37438c12013-10-14 16:20:05 +03002003remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05002004 mgmt_pending_remove(cmd);
2005
2006unlock:
2007 hci_dev_unlock(hdev);
2008}
2009
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002010static int set_connectable_update_settings(struct hci_dev *hdev,
2011 struct sock *sk, u8 val)
2012{
2013 bool changed = false;
2014 int err;
2015
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002016 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002017 changed = true;
2018
2019 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07002020 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002021 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002022 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
2023 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002024 }
2025
2026 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
2027 if (err < 0)
2028 return err;
2029
Johan Hedberg562064e2014-07-08 16:35:34 +03002030 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02002031 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03002032 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002033 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03002034 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002035
2036 return 0;
2037}
2038
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002039static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002040 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002041{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002042 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002043 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002044 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002045 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002046 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002047
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002048 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002049
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002050 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2051 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002052 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2053 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002054
Johan Hedberga7e80f22013-01-09 16:05:19 +02002055 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002056 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2057 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002058
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002059 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002060
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002061 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002062 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002063 goto failed;
2064 }
2065
Johan Hedberg333ae952015-03-17 13:48:47 +02002066 if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
2067 pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002068 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2069 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002070 goto failed;
2071 }
2072
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002073 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2074 if (!cmd) {
2075 err = -ENOMEM;
2076 goto failed;
2077 }
2078
Johan Hedberg2b76f452013-03-15 17:07:04 -05002079 hci_req_init(&req, hdev);
2080
Johan Hedberg9a43e252013-10-20 19:00:07 +03002081 /* If BR/EDR is not enabled and we disable advertising as a
2082 * by-product of disabling connectable, we need to update the
2083 * advertising flags.
2084 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002085 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002086 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002087 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2088 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002089 }
2090 update_adv_data(&req);
2091 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002092 if (cp->val) {
2093 scan = SCAN_PAGE;
2094 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002095 /* If we don't have any whitelist entries just
2096 * disable all scanning. If there are entries
2097 * and we had both page and inquiry scanning
2098 * enabled then fall back to only page scanning.
2099 * Otherwise no changes are needed.
2100 */
2101 if (list_empty(&hdev->whitelist))
2102 scan = SCAN_DISABLED;
2103 else if (test_bit(HCI_ISCAN, &hdev->flags))
2104 scan = SCAN_PAGE;
2105 else
2106 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002107
2108 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002109 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002110 cancel_delayed_work(&hdev->discov_off);
2111 }
2112
2113 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2114 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002115
Johan Hedberg3bd27242014-07-28 20:53:58 +03002116no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002117 /* Update the advertising parameters if necessary */
Arman Uguray880897d2015-03-28 12:39:00 -07002118 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2119 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002120 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002121
Johan Hedberg2b76f452013-03-15 17:07:04 -05002122 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002123 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002124 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002125 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002126 err = set_connectable_update_settings(hdev, sk,
2127 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002128 goto failed;
2129 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002130
2131failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002132 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002133 return err;
2134}
2135
Johan Hedbergb2939472014-07-30 09:22:23 +03002136static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002137 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002138{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002139 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002140 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002141 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002142
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002143 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002144
Johan Hedberga7e80f22013-01-09 16:05:19 +02002145 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002146 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2147 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002148
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002149 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002150
2151 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002152 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002153 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002154 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002155
Johan Hedbergb2939472014-07-30 09:22:23 +03002156 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002157 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002158 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002159
Marcel Holtmann55594352013-10-06 16:11:57 -07002160 if (changed)
2161 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002162
Marcel Holtmann55594352013-10-06 16:11:57 -07002163unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002164 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002165 return err;
2166}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002167
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002168static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2169 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002170{
2171 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002172 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002173 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002174 int err;
2175
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002176 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002177
Johan Hedberge6fe7982013-10-02 15:45:22 +03002178 status = mgmt_bredr_support(hdev);
2179 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002180 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2181 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002182
Johan Hedberga7e80f22013-01-09 16:05:19 +02002183 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002184 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2185 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002186
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002187 hci_dev_lock(hdev);
2188
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002189 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002190 bool changed = false;
2191
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002192 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002193 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002194 changed = true;
2195 }
2196
2197 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2198 if (err < 0)
2199 goto failed;
2200
2201 if (changed)
2202 err = new_settings(hdev, sk);
2203
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002204 goto failed;
2205 }
2206
Johan Hedberg333ae952015-03-17 13:48:47 +02002207 if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002208 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2209 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002210 goto failed;
2211 }
2212
2213 val = !!cp->val;
2214
2215 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2216 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2217 goto failed;
2218 }
2219
2220 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2221 if (!cmd) {
2222 err = -ENOMEM;
2223 goto failed;
2224 }
2225
2226 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2227 if (err < 0) {
2228 mgmt_pending_remove(cmd);
2229 goto failed;
2230 }
2231
2232failed:
2233 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002234 return err;
2235}
2236
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002237static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002238{
2239 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002240 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002241 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002242 int err;
2243
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002244 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002245
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002246 status = mgmt_bredr_support(hdev);
2247 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002248 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002249
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002250 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002251 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2252 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002253
Johan Hedberga7e80f22013-01-09 16:05:19 +02002254 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002255 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2256 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002257
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002258 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002259
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002260 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002261 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002262
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002263 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002264 changed = !hci_dev_test_and_set_flag(hdev,
2265 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002266 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002267 changed = hci_dev_test_and_clear_flag(hdev,
2268 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002269 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002270 changed = hci_dev_test_and_clear_flag(hdev,
2271 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002272 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002273 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002274 }
2275
2276 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2277 if (err < 0)
2278 goto failed;
2279
2280 if (changed)
2281 err = new_settings(hdev, sk);
2282
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002283 goto failed;
2284 }
2285
Johan Hedberg333ae952015-03-17 13:48:47 +02002286 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002287 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2288 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002289 goto failed;
2290 }
2291
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002292 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002293 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2294 goto failed;
2295 }
2296
2297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2298 if (!cmd) {
2299 err = -ENOMEM;
2300 goto failed;
2301 }
2302
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002303 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002304 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2305 sizeof(cp->val), &cp->val);
2306
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002307 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002308 if (err < 0) {
2309 mgmt_pending_remove(cmd);
2310 goto failed;
2311 }
2312
2313failed:
2314 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002315 return err;
2316}
2317
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002318static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002319{
2320 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002321 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002322 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002323 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002325 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002326
Johan Hedberge6fe7982013-10-02 15:45:22 +03002327 status = mgmt_bredr_support(hdev);
2328 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002329 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002330
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002331 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002332 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2333 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002334
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002335 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002336 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2337 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002338
Johan Hedberga7e80f22013-01-09 16:05:19 +02002339 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002340 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2341 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002342
Marcel Holtmannee392692013-10-01 22:59:23 -07002343 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002344
Johan Hedberg333ae952015-03-17 13:48:47 +02002345 if (pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002346 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2347 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002348 goto unlock;
2349 }
2350
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002351 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002352 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002353 } else {
2354 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002355 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2356 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002357 goto unlock;
2358 }
2359
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002360 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002361 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002362
2363 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2364 if (err < 0)
2365 goto unlock;
2366
2367 if (changed)
2368 err = new_settings(hdev, sk);
2369
2370unlock:
2371 hci_dev_unlock(hdev);
2372 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002373}
2374
Marcel Holtmann1904a852015-01-11 13:50:44 -08002375static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002376{
2377 struct cmd_lookup match = { NULL, hdev };
2378
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302379 hci_dev_lock(hdev);
2380
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002381 if (status) {
2382 u8 mgmt_err = mgmt_status(status);
2383
2384 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2385 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302386 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002387 }
2388
2389 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2390
2391 new_settings(hdev, match.sk);
2392
2393 if (match.sk)
2394 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002395
2396 /* Make sure the controller has a good default for
2397 * advertising data. Restrict the update to when LE
2398 * has actually been enabled. During power on, the
2399 * update in powered_update_hci will take care of it.
2400 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002401 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002402 struct hci_request req;
2403
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002404 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002405 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002406 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002407 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002408 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002409 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302410
2411unlock:
2412 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002413}
2414
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002415static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002416{
2417 struct mgmt_mode *cp = data;
2418 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002419 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002420 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002421 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002422 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002423
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002424 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002425
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002426 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002427 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2428 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002429
Johan Hedberga7e80f22013-01-09 16:05:19 +02002430 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002431 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2432 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002433
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002434 /* Bluetooth single mode LE only controllers or dual-mode
2435 * controllers configured as LE only devices, do not allow
2436 * switching LE off. These have either LE enabled explicitly
2437 * or BR/EDR has been previously switched off.
2438 *
2439 * When trying to enable an already enabled LE, then gracefully
2440 * send a positive response. Trying to disable it however will
2441 * result into rejection.
2442 */
2443 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
2444 if (cp->val == 0x01)
2445 return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2446
Johan Hedberga69e8372015-03-06 21:08:53 +02002447 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2448 MGMT_STATUS_REJECTED);
Marcel Holtmanne7844ee2015-03-18 16:15:07 -07002449 }
Johan Hedbergc73eee92013-04-19 18:35:21 +03002450
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002451 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002452
2453 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002454 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002455
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002456 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002457 bool changed = false;
2458
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002459 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002460 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002461 changed = true;
2462 }
2463
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002464 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002465 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002466 changed = true;
2467 }
2468
Johan Hedberg06199cf2012-02-22 16:37:11 +02002469 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2470 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002471 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002472
2473 if (changed)
2474 err = new_settings(hdev, sk);
2475
Johan Hedberg1de028c2012-02-29 19:55:35 -08002476 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002477 }
2478
Johan Hedberg333ae952015-03-17 13:48:47 +02002479 if (pending_find(MGMT_OP_SET_LE, hdev) ||
2480 pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002481 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2482 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002483 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002484 }
2485
2486 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2487 if (!cmd) {
2488 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002489 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002490 }
2491
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002492 hci_req_init(&req, hdev);
2493
Johan Hedberg06199cf2012-02-22 16:37:11 +02002494 memset(&hci_cp, 0, sizeof(hci_cp));
2495
2496 if (val) {
2497 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002498 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002499 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002500 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002501 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002502 }
2503
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002504 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2505 &hci_cp);
2506
2507 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302508 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002509 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002510
Johan Hedberg1de028c2012-02-29 19:55:35 -08002511unlock:
2512 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002513 return err;
2514}
2515
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002516/* This is a helper function to test for pending mgmt commands that can
2517 * cause CoD or EIR HCI commands. We can only allow one such pending
2518 * mgmt command at a time since otherwise we cannot easily track what
2519 * the current values are, will be, and based on that calculate if a new
2520 * HCI command needs to be sent and if yes with what value.
2521 */
2522static bool pending_eir_or_class(struct hci_dev *hdev)
2523{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002524 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002525
2526 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2527 switch (cmd->opcode) {
2528 case MGMT_OP_ADD_UUID:
2529 case MGMT_OP_REMOVE_UUID:
2530 case MGMT_OP_SET_DEV_CLASS:
2531 case MGMT_OP_SET_POWERED:
2532 return true;
2533 }
2534 }
2535
2536 return false;
2537}
2538
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002539static const u8 bluetooth_base_uuid[] = {
2540 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2541 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2542};
2543
2544static u8 get_uuid_size(const u8 *uuid)
2545{
2546 u32 val;
2547
2548 if (memcmp(uuid, bluetooth_base_uuid, 12))
2549 return 128;
2550
2551 val = get_unaligned_le32(&uuid[12]);
2552 if (val > 0xffff)
2553 return 32;
2554
2555 return 16;
2556}
2557
Johan Hedberg92da6092013-03-15 17:06:55 -05002558static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2559{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002560 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002561
2562 hci_dev_lock(hdev);
2563
Johan Hedberg333ae952015-03-17 13:48:47 +02002564 cmd = pending_find(mgmt_op, hdev);
Johan Hedberg92da6092013-03-15 17:06:55 -05002565 if (!cmd)
2566 goto unlock;
2567
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002568 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2569 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002570
2571 mgmt_pending_remove(cmd);
2572
2573unlock:
2574 hci_dev_unlock(hdev);
2575}
2576
Marcel Holtmann1904a852015-01-11 13:50:44 -08002577static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002578{
2579 BT_DBG("status 0x%02x", status);
2580
2581 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2582}
2583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002584static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002585{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002586 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002587 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002588 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002589 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002590 int err;
2591
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002593
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002594 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002595
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002596 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002597 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2598 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002599 goto failed;
2600 }
2601
Andre Guedes92c4c202012-06-07 19:05:44 -03002602 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002603 if (!uuid) {
2604 err = -ENOMEM;
2605 goto failed;
2606 }
2607
2608 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002609 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002610 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002611
Johan Hedbergde66aa62013-01-27 00:31:27 +02002612 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002613
Johan Hedberg890ea892013-03-15 17:06:52 -05002614 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002615
Johan Hedberg890ea892013-03-15 17:06:52 -05002616 update_class(&req);
2617 update_eir(&req);
2618
Johan Hedberg92da6092013-03-15 17:06:55 -05002619 err = hci_req_run(&req, add_uuid_complete);
2620 if (err < 0) {
2621 if (err != -ENODATA)
2622 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002623
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002624 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2625 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002626 goto failed;
2627 }
2628
2629 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002630 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002631 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002632 goto failed;
2633 }
2634
2635 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002636
2637failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002638 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002639 return err;
2640}
2641
Johan Hedberg24b78d02012-02-23 23:24:30 +02002642static bool enable_service_cache(struct hci_dev *hdev)
2643{
2644 if (!hdev_is_powered(hdev))
2645 return false;
2646
Marcel Holtmann238be782015-03-13 02:11:06 -07002647 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002648 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2649 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002650 return true;
2651 }
2652
2653 return false;
2654}
2655
Marcel Holtmann1904a852015-01-11 13:50:44 -08002656static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002657{
2658 BT_DBG("status 0x%02x", status);
2659
2660 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2661}
2662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002663static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002664 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002665{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002666 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002667 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002668 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002669 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg890ea892013-03-15 17:06:52 -05002670 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002671 int err, found;
2672
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002673 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002674
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002675 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002676
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002677 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002678 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2679 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002680 goto unlock;
2681 }
2682
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002683 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002684 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002685
Johan Hedberg24b78d02012-02-23 23:24:30 +02002686 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002687 err = mgmt_cmd_complete(sk, hdev->id,
2688 MGMT_OP_REMOVE_UUID,
2689 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002690 goto unlock;
2691 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002692
Johan Hedberg9246a862012-02-23 21:33:16 +02002693 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002694 }
2695
2696 found = 0;
2697
Johan Hedberg056341c2013-01-27 00:31:30 +02002698 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002699 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2700 continue;
2701
2702 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002703 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002704 found++;
2705 }
2706
2707 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002708 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2709 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002710 goto unlock;
2711 }
2712
Johan Hedberg9246a862012-02-23 21:33:16 +02002713update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002714 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002715
Johan Hedberg890ea892013-03-15 17:06:52 -05002716 update_class(&req);
2717 update_eir(&req);
2718
Johan Hedberg92da6092013-03-15 17:06:55 -05002719 err = hci_req_run(&req, remove_uuid_complete);
2720 if (err < 0) {
2721 if (err != -ENODATA)
2722 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002723
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002724 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2725 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002726 goto unlock;
2727 }
2728
2729 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002730 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002731 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002732 goto unlock;
2733 }
2734
2735 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002736
2737unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002738 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002739 return err;
2740}
2741
Marcel Holtmann1904a852015-01-11 13:50:44 -08002742static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002743{
2744 BT_DBG("status 0x%02x", status);
2745
2746 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2747}
2748
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002749static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002750 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002751{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002752 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002753 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002754 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002755 int err;
2756
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002757 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002758
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002759 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002760 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2761 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002762
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002763 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002764
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002765 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002766 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2767 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002768 goto unlock;
2769 }
2770
2771 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002772 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2773 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002774 goto unlock;
2775 }
2776
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002777 hdev->major_class = cp->major;
2778 hdev->minor_class = cp->minor;
2779
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002780 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002781 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2782 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002783 goto unlock;
2784 }
2785
Johan Hedberg890ea892013-03-15 17:06:52 -05002786 hci_req_init(&req, hdev);
2787
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002788 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002789 hci_dev_unlock(hdev);
2790 cancel_delayed_work_sync(&hdev->service_cache);
2791 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002792 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002793 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002794
Johan Hedberg890ea892013-03-15 17:06:52 -05002795 update_class(&req);
2796
Johan Hedberg92da6092013-03-15 17:06:55 -05002797 err = hci_req_run(&req, set_class_complete);
2798 if (err < 0) {
2799 if (err != -ENODATA)
2800 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002801
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002802 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2803 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002804 goto unlock;
2805 }
2806
2807 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002808 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002809 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002810 goto unlock;
2811 }
2812
2813 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002814
Johan Hedbergb5235a62012-02-21 14:32:24 +02002815unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002816 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002817 return err;
2818}
2819
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002820static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002821 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002822{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002823 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002824 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2825 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002826 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002827 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002828 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002829
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002830 BT_DBG("request for %s", hdev->name);
2831
2832 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002833 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2834 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002835
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002836 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002837 if (key_count > max_key_count) {
2838 BT_ERR("load_link_keys: too big key_count value %u",
2839 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002840 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2841 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002842 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002843
Johan Hedberg86742e12011-11-07 23:13:38 +02002844 expected_len = sizeof(*cp) + key_count *
2845 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002846 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002847 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002848 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002849 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2850 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002851 }
2852
Johan Hedberg4ae14302013-01-20 14:27:13 +02002853 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002854 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2855 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002856
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002857 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002858 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002859
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002860 for (i = 0; i < key_count; i++) {
2861 struct mgmt_link_key_info *key = &cp->keys[i];
2862
Marcel Holtmann8e991132014-01-10 02:07:25 -08002863 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002864 return mgmt_cmd_status(sk, hdev->id,
2865 MGMT_OP_LOAD_LINK_KEYS,
2866 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002867 }
2868
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002869 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002870
2871 hci_link_keys_clear(hdev);
2872
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002873 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002874 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002875 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002876 changed = hci_dev_test_and_clear_flag(hdev,
2877 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002878
2879 if (changed)
2880 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002881
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002882 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002883 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002884
Johan Hedberg58e92932014-06-24 14:00:26 +03002885 /* Always ignore debug keys and require a new pairing if
2886 * the user wants to use them.
2887 */
2888 if (key->type == HCI_LK_DEBUG_COMBINATION)
2889 continue;
2890
Johan Hedberg7652ff62014-06-24 13:15:49 +03002891 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2892 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002893 }
2894
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002895 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002896
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002897 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002898
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002899 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002900}
2901
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002902static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002903 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002904{
2905 struct mgmt_ev_device_unpaired ev;
2906
2907 bacpy(&ev.addr.bdaddr, bdaddr);
2908 ev.addr.type = addr_type;
2909
2910 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002911 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002912}
2913
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002914static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002915 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002916{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002917 struct mgmt_cp_unpair_device *cp = data;
2918 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002919 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002920 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002921 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002922 int err;
2923
Johan Hedberga8a1d192011-11-10 15:54:38 +02002924 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002925 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2926 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002927
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002928 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002929 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2930 MGMT_STATUS_INVALID_PARAMS,
2931 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002932
Johan Hedberg118da702013-01-20 14:27:20 +02002933 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002934 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2935 MGMT_STATUS_INVALID_PARAMS,
2936 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002937
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002938 hci_dev_lock(hdev);
2939
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002940 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002941 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2942 MGMT_STATUS_NOT_POWERED, &rp,
2943 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002944 goto unlock;
2945 }
2946
Johan Hedberge0b2b272014-02-18 17:14:31 +02002947 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002948 /* If disconnection is requested, then look up the
2949 * connection. If the remote device is connected, it
2950 * will be later used to terminate the link.
2951 *
2952 * Setting it to NULL explicitly will cause no
2953 * termination of the link.
2954 */
2955 if (cp->disconnect)
2956 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2957 &cp->addr.bdaddr);
2958 else
2959 conn = NULL;
2960
Johan Hedberg124f6e32012-02-09 13:50:12 +02002961 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002962 } else {
2963 u8 addr_type;
2964
Johan Hedbergd4815c12015-10-19 10:51:47 +03002965 if (cp->addr.type == BDADDR_LE_PUBLIC)
2966 addr_type = ADDR_LE_DEV_PUBLIC;
2967 else
2968 addr_type = ADDR_LE_DEV_RANDOM;
2969
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002970 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2971 &cp->addr.bdaddr);
2972 if (conn) {
2973 /* Defer clearing up the connection parameters
2974 * until closing to give a chance of keeping
2975 * them if a repairing happens.
2976 */
2977 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2978
2979 /* If disconnection is not requested, then
2980 * clear the connection variable so that the
2981 * link is not terminated.
2982 */
2983 if (!cp->disconnect)
2984 conn = NULL;
Johan Hedbergd4815c12015-10-19 10:51:47 +03002985 } else {
2986 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002987 }
2988
Johan Hedberga7ec7332014-02-18 17:14:35 +02002989 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2990
Johan Hedberge0b2b272014-02-18 17:14:31 +02002991 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2992 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002993
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002994 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002995 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2996 MGMT_STATUS_NOT_PAIRED, &rp,
2997 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002998 goto unlock;
2999 }
3000
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003001 /* If the connection variable is set, then termination of the
3002 * link is requested.
3003 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02003004 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003005 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
3006 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02003007 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003008 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003009 }
3010
Johan Hedberg124f6e32012-02-09 13:50:12 +02003011 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003012 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02003013 if (!cmd) {
3014 err = -ENOMEM;
3015 goto unlock;
3016 }
3017
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02003018 cmd->cmd_complete = addr_cmd_complete;
3019
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003020 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02003021 dc.reason = 0x13; /* Remote User Terminated Connection */
3022 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
3023 if (err < 0)
3024 mgmt_pending_remove(cmd);
3025
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003026unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003027 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02003028 return err;
3029}
3030
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003031static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003032 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02003033{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003034 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02003035 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003036 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003037 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003038 int err;
3039
3040 BT_DBG("");
3041
Johan Hedberg06a63b12013-01-20 14:27:21 +02003042 memset(&rp, 0, sizeof(rp));
3043 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3044 rp.addr.type = cp->addr.type;
3045
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003046 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003047 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3048 MGMT_STATUS_INVALID_PARAMS,
3049 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003050
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003051 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003052
3053 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003054 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3055 MGMT_STATUS_NOT_POWERED, &rp,
3056 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003057 goto failed;
3058 }
3059
Johan Hedberg333ae952015-03-17 13:48:47 +02003060 if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003061 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3062 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003063 goto failed;
3064 }
3065
Andre Guedes591f47f2012-04-24 21:02:49 -03003066 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003067 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3068 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003069 else
3070 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003071
Vishal Agarwalf9607272012-06-13 05:32:43 +05303072 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003073 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3074 MGMT_STATUS_NOT_CONNECTED, &rp,
3075 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003076 goto failed;
3077 }
3078
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003079 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003080 if (!cmd) {
3081 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003082 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003083 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003084
Johan Hedbergf5818c22014-12-05 13:36:02 +02003085 cmd->cmd_complete = generic_cmd_complete;
3086
Johan Hedberge3f2f922014-08-18 20:33:33 +03003087 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003088 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003089 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003090
3091failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003092 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003093 return err;
3094}
3095
Andre Guedes57c14772012-04-24 21:02:50 -03003096static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003097{
3098 switch (link_type) {
3099 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003100 switch (addr_type) {
3101 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003102 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003103
Johan Hedberg48264f02011-11-09 13:58:58 +02003104 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003105 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003106 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003107 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003108
Johan Hedberg4c659c32011-11-07 23:13:39 +02003109 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003110 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003111 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003112 }
3113}
3114
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003115static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3116 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003117{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003118 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003119 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003120 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003121 int err;
3122 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003123
3124 BT_DBG("");
3125
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003126 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003127
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003128 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003129 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3130 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003131 goto unlock;
3132 }
3133
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003134 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003135 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3136 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003137 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003138 }
3139
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003140 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003141 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003142 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003143 err = -ENOMEM;
3144 goto unlock;
3145 }
3146
Johan Hedberg2784eb42011-01-21 13:56:35 +02003147 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003148 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003149 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3150 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003151 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003152 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003153 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003154 continue;
3155 i++;
3156 }
3157
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003158 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003159
Johan Hedberg4c659c32011-11-07 23:13:39 +02003160 /* Recalculate length in case of filtered SCO connections, etc */
3161 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003162
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003163 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3164 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003165
Johan Hedberga38528f2011-01-22 06:46:43 +02003166 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003167
3168unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003169 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003170 return err;
3171}
3172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003173static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003174 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003175{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003176 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003177 int err;
3178
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003179 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003180 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003181 if (!cmd)
3182 return -ENOMEM;
3183
Johan Hedbergd8457692012-02-17 14:24:57 +02003184 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003185 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003186 if (err < 0)
3187 mgmt_pending_remove(cmd);
3188
3189 return err;
3190}
3191
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003192static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003193 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003194{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003195 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003196 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003197 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003198 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003199 int err;
3200
3201 BT_DBG("");
3202
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003203 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003204
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003205 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003206 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3207 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003208 goto failed;
3209 }
3210
Johan Hedbergd8457692012-02-17 14:24:57 +02003211 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003212 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003213 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3214 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003215 goto failed;
3216 }
3217
3218 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003219 struct mgmt_cp_pin_code_neg_reply ncp;
3220
3221 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003222
3223 BT_ERR("PIN code is not 16 bytes long");
3224
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003225 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003226 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003227 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3228 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003229
3230 goto failed;
3231 }
3232
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003233 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003234 if (!cmd) {
3235 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003236 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003237 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003238
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003239 cmd->cmd_complete = addr_cmd_complete;
3240
Johan Hedbergd8457692012-02-17 14:24:57 +02003241 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003242 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003243 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003244
3245 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3246 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003247 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003248
3249failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003250 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003251 return err;
3252}
3253
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003254static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3255 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003256{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003257 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003258
3259 BT_DBG("");
3260
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003261 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003262 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3263 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003264
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003265 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003266
3267 hdev->io_capability = cp->io_capability;
3268
3269 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003270 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003271
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003272 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003273
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003274 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3275 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003276}
3277
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003278static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003279{
3280 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003281 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003283 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003284 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3285 continue;
3286
Johan Hedberge9a416b2011-02-19 12:05:56 -03003287 if (cmd->user_data != conn)
3288 continue;
3289
3290 return cmd;
3291 }
3292
3293 return NULL;
3294}
3295
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003296static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003297{
3298 struct mgmt_rp_pair_device rp;
3299 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003300 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003301
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003302 bacpy(&rp.addr.bdaddr, &conn->dst);
3303 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003304
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003305 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3306 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003307
3308 /* So we don't get further callbacks for this connection */
3309 conn->connect_cfm_cb = NULL;
3310 conn->security_cfm_cb = NULL;
3311 conn->disconn_cfm_cb = NULL;
3312
David Herrmann76a68ba2013-04-06 20:28:37 +02003313 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003314
3315 /* The device is paired so there is no need to remove
3316 * its connection parameters anymore.
3317 */
3318 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003319
3320 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003321
3322 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003323}
3324
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003325void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3326{
3327 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003328 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003329
3330 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003331 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003332 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003333 mgmt_pending_remove(cmd);
3334 }
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003335}
3336
Johan Hedberge9a416b2011-02-19 12:05:56 -03003337static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3338{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003339 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003340
3341 BT_DBG("status %u", status);
3342
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003343 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003344 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003345 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003346 return;
3347 }
3348
3349 cmd->cmd_complete(cmd, mgmt_status(status));
3350 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003351}
3352
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003353static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303354{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003355 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303356
3357 BT_DBG("status %u", status);
3358
3359 if (!status)
3360 return;
3361
3362 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003363 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303364 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003365 return;
3366 }
3367
3368 cmd->cmd_complete(cmd, mgmt_status(status));
3369 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303370}
3371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003372static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003373 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003374{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003375 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003376 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003377 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003378 u8 sec_level, auth_type;
3379 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003380 int err;
3381
3382 BT_DBG("");
3383
Szymon Jancf950a30e2013-01-18 12:48:07 +01003384 memset(&rp, 0, sizeof(rp));
3385 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3386 rp.addr.type = cp->addr.type;
3387
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003388 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003389 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3390 MGMT_STATUS_INVALID_PARAMS,
3391 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003392
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003393 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003394 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3395 MGMT_STATUS_INVALID_PARAMS,
3396 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003397
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003398 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003399
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003400 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003401 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3402 MGMT_STATUS_NOT_POWERED, &rp,
3403 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003404 goto unlock;
3405 }
3406
Johan Hedberg55e76b32015-03-10 22:34:40 +02003407 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3408 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3409 MGMT_STATUS_ALREADY_PAIRED, &rp,
3410 sizeof(rp));
3411 goto unlock;
3412 }
3413
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003414 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003415 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003416
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003417 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003418 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3419 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003420 } else {
3421 u8 addr_type;
3422
3423 /* Convert from L2CAP channel address type to HCI address type
3424 */
3425 if (cp->addr.type == BDADDR_LE_PUBLIC)
3426 addr_type = ADDR_LE_DEV_PUBLIC;
3427 else
3428 addr_type = ADDR_LE_DEV_RANDOM;
3429
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003430 /* When pairing a new device, it is expected to remember
3431 * this device for future connections. Adding the connection
3432 * parameter information ahead of time allows tracking
3433 * of the slave preferred values and will speed up any
3434 * further connection establishment.
3435 *
3436 * If connection parameters already exist, then they
3437 * will be kept and this function does nothing.
3438 */
3439 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3440
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003441 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003442 sec_level, HCI_LE_CONN_TIMEOUT,
3443 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003444 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003445
Ville Tervo30e76272011-02-22 16:10:53 -03003446 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003447 int status;
3448
3449 if (PTR_ERR(conn) == -EBUSY)
3450 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003451 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3452 status = MGMT_STATUS_NOT_SUPPORTED;
3453 else if (PTR_ERR(conn) == -ECONNREFUSED)
3454 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003455 else
3456 status = MGMT_STATUS_CONNECT_FAILED;
3457
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003458 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3459 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003460 goto unlock;
3461 }
3462
3463 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003464 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003465 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3466 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003467 goto unlock;
3468 }
3469
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003470 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003471 if (!cmd) {
3472 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003473 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003474 goto unlock;
3475 }
3476
Johan Hedberg04ab2742014-12-05 13:36:04 +02003477 cmd->cmd_complete = pairing_complete;
3478
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003479 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003480 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003481 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003482 conn->security_cfm_cb = pairing_complete_cb;
3483 conn->disconn_cfm_cb = pairing_complete_cb;
3484 } else {
3485 conn->connect_cfm_cb = le_pairing_complete_cb;
3486 conn->security_cfm_cb = le_pairing_complete_cb;
3487 conn->disconn_cfm_cb = le_pairing_complete_cb;
3488 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003489
Johan Hedberge9a416b2011-02-19 12:05:56 -03003490 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003491 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003492
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003493 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003494 hci_conn_security(conn, sec_level, auth_type, true)) {
3495 cmd->cmd_complete(cmd, 0);
3496 mgmt_pending_remove(cmd);
3497 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003498
3499 err = 0;
3500
3501unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003502 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003503 return err;
3504}
3505
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003506static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3507 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003508{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003509 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003510 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003511 struct hci_conn *conn;
3512 int err;
3513
3514 BT_DBG("");
3515
Johan Hedberg28424702012-02-02 04:02:29 +02003516 hci_dev_lock(hdev);
3517
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003518 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003519 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3520 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003521 goto unlock;
3522 }
3523
Johan Hedberg333ae952015-03-17 13:48:47 +02003524 cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003525 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003526 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3527 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003528 goto unlock;
3529 }
3530
3531 conn = cmd->user_data;
3532
3533 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003534 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3535 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003536 goto unlock;
3537 }
3538
Johan Hedberga511b352014-12-11 21:45:45 +02003539 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3540 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003541
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003542 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3543 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003544unlock:
3545 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003546 return err;
3547}
3548
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003549static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003550 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003551 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003552{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003553 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003554 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003555 int err;
3556
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003557 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003558
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003559 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003560 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3561 MGMT_STATUS_NOT_POWERED, addr,
3562 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003563 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003564 }
3565
Johan Hedberg1707c602013-03-15 17:07:15 -05003566 if (addr->type == BDADDR_BREDR)
3567 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003568 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003569 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003570
Johan Hedberg272d90d2012-02-09 15:26:12 +02003571 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003572 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3573 MGMT_STATUS_NOT_CONNECTED, addr,
3574 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003575 goto done;
3576 }
3577
Johan Hedberg1707c602013-03-15 17:07:15 -05003578 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003579 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003580 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003581 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3582 MGMT_STATUS_SUCCESS, addr,
3583 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003584 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003585 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3586 MGMT_STATUS_FAILED, addr,
3587 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003588
Brian Gix47c15e22011-11-16 13:53:14 -08003589 goto done;
3590 }
3591
Johan Hedberg1707c602013-03-15 17:07:15 -05003592 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003593 if (!cmd) {
3594 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003595 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003596 }
3597
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003598 cmd->cmd_complete = addr_cmd_complete;
3599
Brian Gix0df4c182011-11-16 13:53:13 -08003600 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003601 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3602 struct hci_cp_user_passkey_reply cp;
3603
Johan Hedberg1707c602013-03-15 17:07:15 -05003604 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003605 cp.passkey = passkey;
3606 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3607 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003608 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3609 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003610
Johan Hedberga664b5b2011-02-19 12:06:02 -03003611 if (err < 0)
3612 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003613
Brian Gix0df4c182011-11-16 13:53:13 -08003614done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003615 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003616 return err;
3617}
3618
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303619static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3620 void *data, u16 len)
3621{
3622 struct mgmt_cp_pin_code_neg_reply *cp = data;
3623
3624 BT_DBG("");
3625
Johan Hedberg1707c602013-03-15 17:07:15 -05003626 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303627 MGMT_OP_PIN_CODE_NEG_REPLY,
3628 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3629}
3630
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003631static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3632 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003633{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003634 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003635
3636 BT_DBG("");
3637
3638 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003639 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3640 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003641
Johan Hedberg1707c602013-03-15 17:07:15 -05003642 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003643 MGMT_OP_USER_CONFIRM_REPLY,
3644 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003645}
3646
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003647static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003648 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003649{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003650 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003651
3652 BT_DBG("");
3653
Johan Hedberg1707c602013-03-15 17:07:15 -05003654 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003655 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3656 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003657}
3658
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003659static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3660 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003661{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003662 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003663
3664 BT_DBG("");
3665
Johan Hedberg1707c602013-03-15 17:07:15 -05003666 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003667 MGMT_OP_USER_PASSKEY_REPLY,
3668 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003669}
3670
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003671static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003672 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003673{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003674 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003675
3676 BT_DBG("");
3677
Johan Hedberg1707c602013-03-15 17:07:15 -05003678 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003679 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3680 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003681}
3682
Johan Hedberg13928972013-03-15 17:07:00 -05003683static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003684{
Johan Hedberg13928972013-03-15 17:07:00 -05003685 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003686 struct hci_cp_write_local_name cp;
3687
Johan Hedberg13928972013-03-15 17:07:00 -05003688 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003689
Johan Hedberg890ea892013-03-15 17:06:52 -05003690 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003691}
3692
Marcel Holtmann1904a852015-01-11 13:50:44 -08003693static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003694{
3695 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003696 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003697
3698 BT_DBG("status 0x%02x", status);
3699
3700 hci_dev_lock(hdev);
3701
Johan Hedberg333ae952015-03-17 13:48:47 +02003702 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05003703 if (!cmd)
3704 goto unlock;
3705
3706 cp = cmd->param;
3707
3708 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003709 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3710 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003711 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003712 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3713 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003714
3715 mgmt_pending_remove(cmd);
3716
3717unlock:
3718 hci_dev_unlock(hdev);
3719}
3720
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003721static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003722 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003723{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003724 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003725 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003726 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003727 int err;
3728
3729 BT_DBG("");
3730
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003731 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003732
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003733 /* If the old values are the same as the new ones just return a
3734 * direct command complete event.
3735 */
3736 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3737 !memcmp(hdev->short_name, cp->short_name,
3738 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003739 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3740 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003741 goto failed;
3742 }
3743
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003744 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003745
Johan Hedbergb5235a62012-02-21 14:32:24 +02003746 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003747 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003748
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003749 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3750 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003751 if (err < 0)
3752 goto failed;
3753
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003754 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3755 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003756
Johan Hedbergb5235a62012-02-21 14:32:24 +02003757 goto failed;
3758 }
3759
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003760 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003761 if (!cmd) {
3762 err = -ENOMEM;
3763 goto failed;
3764 }
3765
Johan Hedberg13928972013-03-15 17:07:00 -05003766 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3767
Johan Hedberg890ea892013-03-15 17:06:52 -05003768 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003769
3770 if (lmp_bredr_capable(hdev)) {
3771 update_name(&req);
3772 update_eir(&req);
3773 }
3774
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003775 /* The name is stored in the scan response data and so
3776 * no need to udpate the advertising data here.
3777 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003778 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003779 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003780
Johan Hedberg13928972013-03-15 17:07:00 -05003781 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003782 if (err < 0)
3783 mgmt_pending_remove(cmd);
3784
3785failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003786 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003787 return err;
3788}
3789
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003790static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
3791 u16 opcode, struct sk_buff *skb)
3792{
3793 struct mgmt_rp_read_local_oob_data mgmt_rp;
3794 size_t rp_size = sizeof(mgmt_rp);
3795 struct mgmt_pending_cmd *cmd;
3796
3797 BT_DBG("%s status %u", hdev->name, status);
3798
3799 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
3800 if (!cmd)
3801 return;
3802
3803 if (status || !skb) {
3804 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3805 status ? mgmt_status(status) : MGMT_STATUS_FAILED);
3806 goto remove;
3807 }
3808
3809 memset(&mgmt_rp, 0, sizeof(mgmt_rp));
3810
3811 if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
3812 struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
3813
3814 if (skb->len < sizeof(*rp)) {
3815 mgmt_cmd_status(cmd->sk, hdev->id,
3816 MGMT_OP_READ_LOCAL_OOB_DATA,
3817 MGMT_STATUS_FAILED);
3818 goto remove;
3819 }
3820
3821 memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
3822 memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
3823
3824 rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
3825 } else {
3826 struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
3827
3828 if (skb->len < sizeof(*rp)) {
3829 mgmt_cmd_status(cmd->sk, hdev->id,
3830 MGMT_OP_READ_LOCAL_OOB_DATA,
3831 MGMT_STATUS_FAILED);
3832 goto remove;
3833 }
3834
3835 memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
3836 memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
3837
3838 memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
3839 memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
3840 }
3841
3842 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3843 MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
3844
3845remove:
3846 mgmt_pending_remove(cmd);
3847}
3848
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003849static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003850 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003851{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003852 struct mgmt_pending_cmd *cmd;
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003853 struct hci_request req;
Szymon Jancc35938b2011-03-22 13:12:21 +01003854 int err;
3855
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003856 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003857
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003858 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003859
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003860 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003861 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3862 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003863 goto unlock;
3864 }
3865
Andre Guedes9a1a1992012-07-24 15:03:48 -03003866 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003867 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3868 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003869 goto unlock;
3870 }
3871
Johan Hedberg333ae952015-03-17 13:48:47 +02003872 if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003873 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3874 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003875 goto unlock;
3876 }
3877
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003878 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003879 if (!cmd) {
3880 err = -ENOMEM;
3881 goto unlock;
3882 }
3883
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003884 hci_req_init(&req, hdev);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003885
Johan Hedberg1b9441f2015-04-02 13:41:13 +03003886 if (bredr_sc_enabled(hdev))
3887 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
3888 else
3889 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3890
3891 err = hci_req_run_skb(&req, read_local_oob_data_complete);
Szymon Jancc35938b2011-03-22 13:12:21 +01003892 if (err < 0)
3893 mgmt_pending_remove(cmd);
3894
3895unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003896 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003897 return err;
3898}
3899
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003900static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003901 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003902{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003903 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003904 int err;
3905
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003906 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003907
Johan Hedberg5d57e792015-01-23 10:10:38 +02003908 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003909 return mgmt_cmd_complete(sk, hdev->id,
3910 MGMT_OP_ADD_REMOTE_OOB_DATA,
3911 MGMT_STATUS_INVALID_PARAMS,
3912 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003913
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003914 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003915
Marcel Holtmannec109112014-01-10 02:07:30 -08003916 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3917 struct mgmt_cp_add_remote_oob_data *cp = data;
3918 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003919
Johan Hedbergc19a4952014-11-17 20:52:19 +02003920 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003921 err = mgmt_cmd_complete(sk, hdev->id,
3922 MGMT_OP_ADD_REMOTE_OOB_DATA,
3923 MGMT_STATUS_INVALID_PARAMS,
3924 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003925 goto unlock;
3926 }
3927
Marcel Holtmannec109112014-01-10 02:07:30 -08003928 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003929 cp->addr.type, cp->hash,
3930 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003931 if (err < 0)
3932 status = MGMT_STATUS_FAILED;
3933 else
3934 status = MGMT_STATUS_SUCCESS;
3935
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003936 err = mgmt_cmd_complete(sk, hdev->id,
3937 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3938 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003939 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3940 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003941 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003942 u8 status;
3943
Johan Hedberg86df9202014-10-26 20:52:27 +01003944 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003945 /* Enforce zero-valued 192-bit parameters as
3946 * long as legacy SMP OOB isn't implemented.
3947 */
3948 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3949 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003950 err = mgmt_cmd_complete(sk, hdev->id,
3951 MGMT_OP_ADD_REMOTE_OOB_DATA,
3952 MGMT_STATUS_INVALID_PARAMS,
3953 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003954 goto unlock;
3955 }
3956
Johan Hedberg86df9202014-10-26 20:52:27 +01003957 rand192 = NULL;
3958 hash192 = NULL;
3959 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003960 /* In case one of the P-192 values is set to zero,
3961 * then just disable OOB data for P-192.
3962 */
3963 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3964 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3965 rand192 = NULL;
3966 hash192 = NULL;
3967 } else {
3968 rand192 = cp->rand192;
3969 hash192 = cp->hash192;
3970 }
3971 }
3972
3973 /* In case one of the P-256 values is set to zero, then just
3974 * disable OOB data for P-256.
3975 */
3976 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3977 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3978 rand256 = NULL;
3979 hash256 = NULL;
3980 } else {
3981 rand256 = cp->rand256;
3982 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003983 }
3984
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003985 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003986 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003987 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003988 if (err < 0)
3989 status = MGMT_STATUS_FAILED;
3990 else
3991 status = MGMT_STATUS_SUCCESS;
3992
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003993 err = mgmt_cmd_complete(sk, hdev->id,
3994 MGMT_OP_ADD_REMOTE_OOB_DATA,
3995 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003996 } else {
3997 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003998 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3999 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08004000 }
Szymon Janc2763eda2011-03-22 13:12:22 +01004001
Johan Hedbergc19a4952014-11-17 20:52:19 +02004002unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004003 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004004 return err;
4005}
4006
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004007static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004008 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01004009{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004010 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004011 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01004012 int err;
4013
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004014 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01004015
Johan Hedbergc19a4952014-11-17 20:52:19 +02004016 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004017 return mgmt_cmd_complete(sk, hdev->id,
4018 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4019 MGMT_STATUS_INVALID_PARAMS,
4020 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02004021
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004022 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004023
Johan Hedbergeedbd582014-11-15 09:34:23 +02004024 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4025 hci_remote_oob_data_clear(hdev);
4026 status = MGMT_STATUS_SUCCESS;
4027 goto done;
4028 }
4029
Johan Hedberg6928a922014-10-26 20:46:09 +01004030 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01004031 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004032 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01004033 else
Szymon Janca6785be2012-12-13 15:11:21 +01004034 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02004035
Johan Hedbergeedbd582014-11-15 09:34:23 +02004036done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004037 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
4038 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01004039
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004040 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01004041 return err;
4042}
4043
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004044static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
4045{
4046 struct hci_dev *hdev = req->hdev;
4047 struct hci_cp_inquiry cp;
4048 /* General inquiry access code (GIAC) */
4049 u8 lap[3] = { 0x33, 0x8b, 0x9e };
4050
4051 *status = mgmt_bredr_support(hdev);
4052 if (*status)
4053 return false;
4054
4055 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
4056 *status = MGMT_STATUS_BUSY;
4057 return false;
4058 }
4059
4060 hci_inquiry_cache_flush(hdev);
4061
4062 memset(&cp, 0, sizeof(cp));
4063 memcpy(&cp.lap, lap, sizeof(cp.lap));
4064 cp.length = DISCOV_BREDR_INQUIRY_LEN;
4065
4066 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
4067
4068 return true;
4069}
4070
4071static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004072{
Marcel Holtmann80190442014-12-04 11:36:36 +01004073 struct hci_dev *hdev = req->hdev;
4074 struct hci_cp_le_set_scan_param param_cp;
4075 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01004076 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004077 int err;
4078
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004079 *status = mgmt_le_support(hdev);
4080 if (*status)
4081 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004082
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004083 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
4084 /* Don't let discovery abort an outgoing connection attempt
4085 * that's using directed advertising.
4086 */
4087 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
4088 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01004089 return false;
4090 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004091
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004092 disable_advertising(req);
4093 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004094
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004095 /* If controller is scanning, it means the background scanning is
4096 * running. Thus, we should temporarily stop it in order to set the
4097 * discovery scanning parameters.
4098 */
4099 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
4100 hci_req_add_le_scan_disable(req);
4101
4102 /* All active scans will be done with either a resolvable private
4103 * address (when privacy feature has been enabled) or non-resolvable
4104 * private address.
4105 */
4106 err = hci_update_random_address(req, true, &own_addr_type);
4107 if (err < 0) {
4108 *status = MGMT_STATUS_FAILED;
4109 return false;
4110 }
4111
4112 memset(&param_cp, 0, sizeof(param_cp));
4113 param_cp.type = LE_SCAN_ACTIVE;
4114 param_cp.interval = cpu_to_le16(interval);
4115 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
4116 param_cp.own_address_type = own_addr_type;
4117
4118 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
4119 &param_cp);
4120
4121 memset(&enable_cp, 0, sizeof(enable_cp));
4122 enable_cp.enable = LE_SCAN_ENABLE;
4123 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4124
4125 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4126 &enable_cp);
4127
4128 return true;
4129}
4130
4131static bool trigger_discovery(struct hci_request *req, u8 *status)
4132{
4133 struct hci_dev *hdev = req->hdev;
4134
4135 switch (hdev->discovery.type) {
4136 case DISCOV_TYPE_BREDR:
4137 if (!trigger_bredr_inquiry(req, status))
4138 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004139 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004140
Marcel Holtmann80190442014-12-04 11:36:36 +01004141 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004142 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4143 &hdev->quirks)) {
4144 /* During simultaneous discovery, we double LE scan
4145 * interval. We must leave some time for the controller
4146 * to do BR/EDR inquiry.
4147 */
4148 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4149 status))
4150 return false;
4151
4152 if (!trigger_bredr_inquiry(req, status))
4153 return false;
4154
4155 return true;
4156 }
4157
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004158 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004159 *status = MGMT_STATUS_NOT_SUPPORTED;
4160 return false;
4161 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004162 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004163
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004164 case DISCOV_TYPE_LE:
4165 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004166 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004167 break;
4168
4169 default:
4170 *status = MGMT_STATUS_INVALID_PARAMS;
4171 return false;
4172 }
4173
4174 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004175}
4176
Marcel Holtmann1904a852015-01-11 13:50:44 -08004177static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4178 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004179{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004180 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004181 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004182
Andre Guedes7c307722013-04-30 15:29:28 -03004183 BT_DBG("status %d", status);
4184
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004185 hci_dev_lock(hdev);
4186
Johan Hedberg333ae952015-03-17 13:48:47 +02004187 cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004188 if (!cmd)
Johan Hedberg333ae952015-03-17 13:48:47 +02004189 cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004190
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004191 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004192 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004193 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004194 }
4195
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004196 if (status) {
4197 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4198 goto unlock;
4199 }
4200
Andre Guedes7c307722013-04-30 15:29:28 -03004201 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004202
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004203 /* If the scan involves LE scan, pick proper timeout to schedule
4204 * hdev->le_scan_disable that will stop it.
4205 */
Andre Guedes7c307722013-04-30 15:29:28 -03004206 switch (hdev->discovery.type) {
4207 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004208 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004209 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004210 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski07d23342015-03-17 09:04:14 -07004211 /* When running simultaneous discovery, the LE scanning time
4212 * should occupy the whole discovery time sine BR/EDR inquiry
4213 * and LE scanning are scheduled by the controller.
4214 *
4215 * For interleaving discovery in comparison, BR/EDR inquiry
4216 * and LE scanning are done sequentially with separate
4217 * timeouts.
4218 */
4219 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4220 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4221 else
4222 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004223 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004224 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004225 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004226 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004227 default:
4228 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004229 timeout = 0;
4230 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004231 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004232
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004233 if (timeout) {
4234 /* When service discovery is used and the controller has
4235 * a strict duplicate filter, it is important to remember
4236 * the start and duration of the scan. This is required
4237 * for restarting scanning during the discovery phase.
4238 */
4239 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4240 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004241 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004242 hdev->discovery.scan_start = jiffies;
4243 hdev->discovery.scan_duration = timeout;
4244 }
4245
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004246 queue_delayed_work(hdev->workqueue,
4247 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004248 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004249
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004250unlock:
4251 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004252}
4253
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004254static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004255 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004256{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004257 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004258 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004259 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004260 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004261 int err;
4262
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004263 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004264
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004265 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004266
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004267 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004268 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4269 MGMT_STATUS_NOT_POWERED,
4270 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004271 goto failed;
4272 }
4273
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004274 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004275 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004276 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4277 MGMT_STATUS_BUSY, &cp->type,
4278 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004279 goto failed;
4280 }
4281
Johan Hedberg2922a942014-12-05 13:36:06 +02004282 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004283 if (!cmd) {
4284 err = -ENOMEM;
4285 goto failed;
4286 }
4287
Johan Hedberg2922a942014-12-05 13:36:06 +02004288 cmd->cmd_complete = generic_cmd_complete;
4289
Marcel Holtmann22078802014-12-05 11:45:22 +01004290 /* Clear the discovery filter first to free any previously
4291 * allocated memory for the UUID list.
4292 */
4293 hci_discovery_filter_clear(hdev);
4294
Andre Guedes4aab14e2012-02-17 20:39:36 -03004295 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004296 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004297
Andre Guedes7c307722013-04-30 15:29:28 -03004298 hci_req_init(&req, hdev);
4299
Marcel Holtmann80190442014-12-04 11:36:36 +01004300 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004301 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4302 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004303 mgmt_pending_remove(cmd);
4304 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004305 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004306
Andre Guedes7c307722013-04-30 15:29:28 -03004307 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004308 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004309 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004310 goto failed;
4311 }
4312
4313 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004314
4315failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004316 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004317 return err;
4318}
4319
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004320static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4321 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004322{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004323 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4324 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004325}
4326
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004327static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4328 void *data, u16 len)
4329{
4330 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004331 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004332 struct hci_request req;
4333 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4334 u16 uuid_count, expected_len;
4335 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004336 int err;
4337
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004338 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004339
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004340 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004341
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004342 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004343 err = mgmt_cmd_complete(sk, hdev->id,
4344 MGMT_OP_START_SERVICE_DISCOVERY,
4345 MGMT_STATUS_NOT_POWERED,
4346 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004347 goto failed;
4348 }
4349
4350 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004351 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004352 err = mgmt_cmd_complete(sk, hdev->id,
4353 MGMT_OP_START_SERVICE_DISCOVERY,
4354 MGMT_STATUS_BUSY, &cp->type,
4355 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004356 goto failed;
4357 }
4358
4359 uuid_count = __le16_to_cpu(cp->uuid_count);
4360 if (uuid_count > max_uuid_count) {
4361 BT_ERR("service_discovery: too big uuid_count value %u",
4362 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004363 err = mgmt_cmd_complete(sk, hdev->id,
4364 MGMT_OP_START_SERVICE_DISCOVERY,
4365 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4366 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004367 goto failed;
4368 }
4369
4370 expected_len = sizeof(*cp) + uuid_count * 16;
4371 if (expected_len != len) {
4372 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4373 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004374 err = mgmt_cmd_complete(sk, hdev->id,
4375 MGMT_OP_START_SERVICE_DISCOVERY,
4376 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4377 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004378 goto failed;
4379 }
4380
4381 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004382 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004383 if (!cmd) {
4384 err = -ENOMEM;
4385 goto failed;
4386 }
4387
Johan Hedberg2922a942014-12-05 13:36:06 +02004388 cmd->cmd_complete = service_discovery_cmd_complete;
4389
Marcel Holtmann22078802014-12-05 11:45:22 +01004390 /* Clear the discovery filter first to free any previously
4391 * allocated memory for the UUID list.
4392 */
4393 hci_discovery_filter_clear(hdev);
4394
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004395 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004396 hdev->discovery.type = cp->type;
4397 hdev->discovery.rssi = cp->rssi;
4398 hdev->discovery.uuid_count = uuid_count;
4399
4400 if (uuid_count > 0) {
4401 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4402 GFP_KERNEL);
4403 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004404 err = mgmt_cmd_complete(sk, hdev->id,
4405 MGMT_OP_START_SERVICE_DISCOVERY,
4406 MGMT_STATUS_FAILED,
4407 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004408 mgmt_pending_remove(cmd);
4409 goto failed;
4410 }
4411 }
4412
4413 hci_req_init(&req, hdev);
4414
4415 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004416 err = mgmt_cmd_complete(sk, hdev->id,
4417 MGMT_OP_START_SERVICE_DISCOVERY,
4418 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004419 mgmt_pending_remove(cmd);
4420 goto failed;
4421 }
4422
4423 err = hci_req_run(&req, start_discovery_complete);
4424 if (err < 0) {
4425 mgmt_pending_remove(cmd);
4426 goto failed;
4427 }
4428
4429 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4430
4431failed:
4432 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004433 return err;
4434}
4435
Marcel Holtmann1904a852015-01-11 13:50:44 -08004436static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004437{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004438 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004439
Andre Guedes0e05bba2013-04-30 15:29:33 -03004440 BT_DBG("status %d", status);
4441
4442 hci_dev_lock(hdev);
4443
Johan Hedberg333ae952015-03-17 13:48:47 +02004444 cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004445 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004446 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004447 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004448 }
4449
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004450 if (!status)
4451 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004452
Andre Guedes0e05bba2013-04-30 15:29:33 -03004453 hci_dev_unlock(hdev);
4454}
4455
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004456static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004457 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004458{
Johan Hedbergd9306502012-02-20 23:25:18 +02004459 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004460 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004461 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004462 int err;
4463
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004464 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004465
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004466 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004467
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004468 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004469 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4470 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4471 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004472 goto unlock;
4473 }
4474
4475 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004476 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4477 MGMT_STATUS_INVALID_PARAMS,
4478 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004479 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004480 }
4481
Johan Hedberg2922a942014-12-05 13:36:06 +02004482 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004483 if (!cmd) {
4484 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004485 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004486 }
4487
Johan Hedberg2922a942014-12-05 13:36:06 +02004488 cmd->cmd_complete = generic_cmd_complete;
4489
Andre Guedes0e05bba2013-04-30 15:29:33 -03004490 hci_req_init(&req, hdev);
4491
Johan Hedberg21a60d32014-06-10 14:05:58 +03004492 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004493
Johan Hedberg21a60d32014-06-10 14:05:58 +03004494 err = hci_req_run(&req, stop_discovery_complete);
4495 if (!err) {
4496 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004497 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004498 }
4499
Johan Hedberg21a60d32014-06-10 14:05:58 +03004500 mgmt_pending_remove(cmd);
4501
4502 /* If no HCI commands were sent we're done */
4503 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004504 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4505 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004506 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4507 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004508
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004509unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004510 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004511 return err;
4512}
4513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004514static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004515 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004516{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004517 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004518 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004519 int err;
4520
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004521 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004522
Johan Hedberg561aafb2012-01-04 13:31:59 +02004523 hci_dev_lock(hdev);
4524
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004525 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004526 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4527 MGMT_STATUS_FAILED, &cp->addr,
4528 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004529 goto failed;
4530 }
4531
Johan Hedberga198e7b2012-02-17 14:27:06 +02004532 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004533 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004534 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4535 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4536 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004537 goto failed;
4538 }
4539
4540 if (cp->name_known) {
4541 e->name_state = NAME_KNOWN;
4542 list_del(&e->list);
4543 } else {
4544 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004545 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004546 }
4547
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004548 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4549 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004550
4551failed:
4552 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004553 return err;
4554}
4555
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004556static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004557 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004558{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004559 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004560 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004561 int err;
4562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004563 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004564
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004565 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004566 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4567 MGMT_STATUS_INVALID_PARAMS,
4568 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004569
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004570 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004571
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004572 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4573 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004574 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004575 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004576 goto done;
4577 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004578
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004579 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4580 sk);
4581 status = MGMT_STATUS_SUCCESS;
4582
4583done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004584 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4585 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004586
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004587 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004588
4589 return err;
4590}
4591
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004592static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004593 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004594{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004595 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004596 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004597 int err;
4598
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004599 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004600
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004601 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004602 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4603 MGMT_STATUS_INVALID_PARAMS,
4604 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004605
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004606 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004607
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004608 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4609 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004610 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004611 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004612 goto done;
4613 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004614
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004615 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4616 sk);
4617 status = MGMT_STATUS_SUCCESS;
4618
4619done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004620 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4621 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004622
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004623 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004624
4625 return err;
4626}
4627
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004628static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4629 u16 len)
4630{
4631 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004632 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004633 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004634 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004635
4636 BT_DBG("%s", hdev->name);
4637
Szymon Jancc72d4b82012-03-16 16:02:57 +01004638 source = __le16_to_cpu(cp->source);
4639
4640 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004641 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4642 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004643
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004644 hci_dev_lock(hdev);
4645
Szymon Jancc72d4b82012-03-16 16:02:57 +01004646 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004647 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4648 hdev->devid_product = __le16_to_cpu(cp->product);
4649 hdev->devid_version = __le16_to_cpu(cp->version);
4650
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004651 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4652 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004653
Johan Hedberg890ea892013-03-15 17:06:52 -05004654 hci_req_init(&req, hdev);
4655 update_eir(&req);
4656 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004657
4658 hci_dev_unlock(hdev);
4659
4660 return err;
4661}
4662
Arman Uguray24b4f382015-03-23 15:57:12 -07004663static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
4664 u16 opcode)
4665{
4666 BT_DBG("status %d", status);
4667}
4668
Marcel Holtmann1904a852015-01-11 13:50:44 -08004669static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4670 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004671{
4672 struct cmd_lookup match = { NULL, hdev };
Arman Uguray24b4f382015-03-23 15:57:12 -07004673 struct hci_request req;
Johan Hedberg4375f102013-09-25 13:26:10 +03004674
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304675 hci_dev_lock(hdev);
4676
Johan Hedberg4375f102013-09-25 13:26:10 +03004677 if (status) {
4678 u8 mgmt_err = mgmt_status(status);
4679
4680 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4681 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304682 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004683 }
4684
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004685 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004686 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004687 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004688 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004689
Johan Hedberg4375f102013-09-25 13:26:10 +03004690 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4691 &match);
4692
4693 new_settings(hdev, match.sk);
4694
4695 if (match.sk)
4696 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304697
Arman Uguray24b4f382015-03-23 15:57:12 -07004698 /* If "Set Advertising" was just disabled and instance advertising was
4699 * set up earlier, then enable the advertising instance.
4700 */
4701 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
4702 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
4703 goto unlock;
4704
4705 hci_req_init(&req, hdev);
4706
4707 update_adv_data(&req);
4708 enable_advertising(&req);
4709
4710 if (hci_req_run(&req, enable_advertising_instance) < 0)
4711 BT_ERR("Failed to re-configure advertising");
4712
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304713unlock:
4714 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004715}
4716
Marcel Holtmann21b51872013-10-10 09:47:53 -07004717static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4718 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004719{
4720 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004721 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004722 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004723 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004724 int err;
4725
4726 BT_DBG("request for %s", hdev->name);
4727
Johan Hedberge6fe7982013-10-02 15:45:22 +03004728 status = mgmt_le_support(hdev);
4729 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004730 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4731 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004732
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004733 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004734 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4735 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004736
4737 hci_dev_lock(hdev);
4738
4739 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004740
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004741 /* The following conditions are ones which mean that we should
4742 * not do any HCI communication but directly send a mgmt
4743 * response to user space (after toggling the flag if
4744 * necessary).
4745 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004746 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004747 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4748 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004749 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004750 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004751 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004752 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004753
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004754 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004755 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004756 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004757 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004758 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004759 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004760 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004761 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004762 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004763 }
4764
4765 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4766 if (err < 0)
4767 goto unlock;
4768
4769 if (changed)
4770 err = new_settings(hdev, sk);
4771
4772 goto unlock;
4773 }
4774
Johan Hedberg333ae952015-03-17 13:48:47 +02004775 if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4776 pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004777 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4778 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004779 goto unlock;
4780 }
4781
4782 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4783 if (!cmd) {
4784 err = -ENOMEM;
4785 goto unlock;
4786 }
4787
4788 hci_req_init(&req, hdev);
4789
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004790 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004791 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004792 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004793 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004794
Arman Uguray24b4f382015-03-23 15:57:12 -07004795 if (val) {
4796 /* Switch to instance "0" for the Set Advertising setting. */
4797 update_adv_data_for_instance(&req, 0);
Arman Uguray4117ed72015-03-23 15:57:14 -07004798 update_scan_rsp_data_for_instance(&req, 0);
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004799 enable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004800 } else {
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004801 disable_advertising(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07004802 }
Johan Hedberg4375f102013-09-25 13:26:10 +03004803
4804 err = hci_req_run(&req, set_advertising_complete);
4805 if (err < 0)
4806 mgmt_pending_remove(cmd);
4807
4808unlock:
4809 hci_dev_unlock(hdev);
4810 return err;
4811}
4812
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004813static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4814 void *data, u16 len)
4815{
4816 struct mgmt_cp_set_static_address *cp = data;
4817 int err;
4818
4819 BT_DBG("%s", hdev->name);
4820
Marcel Holtmann62af4442013-10-02 22:10:32 -07004821 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004822 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4823 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004824
4825 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004826 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4827 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004828
4829 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4830 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004831 return mgmt_cmd_status(sk, hdev->id,
4832 MGMT_OP_SET_STATIC_ADDRESS,
4833 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004834
4835 /* Two most significant bits shall be set */
4836 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004837 return mgmt_cmd_status(sk, hdev->id,
4838 MGMT_OP_SET_STATIC_ADDRESS,
4839 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004840 }
4841
4842 hci_dev_lock(hdev);
4843
4844 bacpy(&hdev->static_addr, &cp->bdaddr);
4845
Marcel Holtmann93690c22015-03-06 10:11:21 -08004846 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4847 if (err < 0)
4848 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004849
Marcel Holtmann93690c22015-03-06 10:11:21 -08004850 err = new_settings(hdev, sk);
4851
4852unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004853 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004854 return err;
4855}
4856
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004857static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4858 void *data, u16 len)
4859{
4860 struct mgmt_cp_set_scan_params *cp = data;
4861 __u16 interval, window;
4862 int err;
4863
4864 BT_DBG("%s", hdev->name);
4865
4866 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004867 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4868 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004869
4870 interval = __le16_to_cpu(cp->interval);
4871
4872 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004873 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4874 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004875
4876 window = __le16_to_cpu(cp->window);
4877
4878 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004879 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4880 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004881
Marcel Holtmann899e1072013-10-14 09:55:32 -07004882 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004883 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4884 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004885
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004886 hci_dev_lock(hdev);
4887
4888 hdev->le_scan_interval = interval;
4889 hdev->le_scan_window = window;
4890
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004891 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4892 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004893
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004894 /* If background scan is running, restart it so new parameters are
4895 * loaded.
4896 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004897 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004898 hdev->discovery.state == DISCOVERY_STOPPED) {
4899 struct hci_request req;
4900
4901 hci_req_init(&req, hdev);
4902
4903 hci_req_add_le_scan_disable(&req);
4904 hci_req_add_le_passive_scan(&req);
4905
4906 hci_req_run(&req, NULL);
4907 }
4908
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004909 hci_dev_unlock(hdev);
4910
4911 return err;
4912}
4913
Marcel Holtmann1904a852015-01-11 13:50:44 -08004914static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4915 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004916{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004917 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004918
4919 BT_DBG("status 0x%02x", status);
4920
4921 hci_dev_lock(hdev);
4922
Johan Hedberg333ae952015-03-17 13:48:47 +02004923 cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004924 if (!cmd)
4925 goto unlock;
4926
4927 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004928 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4929 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004930 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004931 struct mgmt_mode *cp = cmd->param;
4932
4933 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004934 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004935 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004936 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004937
Johan Hedberg33e38b32013-03-15 17:07:05 -05004938 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4939 new_settings(hdev, cmd->sk);
4940 }
4941
4942 mgmt_pending_remove(cmd);
4943
4944unlock:
4945 hci_dev_unlock(hdev);
4946}
4947
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004948static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004949 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004950{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004951 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004952 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004953 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004954 int err;
4955
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004956 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004957
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004958 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004959 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004960 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4961 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004962
Johan Hedberga7e80f22013-01-09 16:05:19 +02004963 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004964 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4965 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004966
Antti Julkuf6422ec2011-06-22 13:11:56 +03004967 hci_dev_lock(hdev);
4968
Johan Hedberg333ae952015-03-17 13:48:47 +02004969 if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004970 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4971 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004972 goto unlock;
4973 }
4974
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004975 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004976 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4977 hdev);
4978 goto unlock;
4979 }
4980
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004981 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004982 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004983 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4984 hdev);
4985 new_settings(hdev, sk);
4986 goto unlock;
4987 }
4988
Johan Hedberg33e38b32013-03-15 17:07:05 -05004989 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4990 data, len);
4991 if (!cmd) {
4992 err = -ENOMEM;
4993 goto unlock;
4994 }
4995
4996 hci_req_init(&req, hdev);
4997
Johan Hedberg406d7802013-03-15 17:07:09 -05004998 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004999
5000 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03005001 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005002 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
5003 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005004 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03005005 }
5006
Johan Hedberg33e38b32013-03-15 17:07:05 -05005007unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03005008 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05005009
Antti Julkuf6422ec2011-06-22 13:11:56 +03005010 return err;
5011}
5012
Marcel Holtmann1904a852015-01-11 13:50:44 -08005013static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03005014{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005015 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005016
5017 BT_DBG("status 0x%02x", status);
5018
5019 hci_dev_lock(hdev);
5020
Johan Hedberg333ae952015-03-17 13:48:47 +02005021 cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005022 if (!cmd)
5023 goto unlock;
5024
5025 if (status) {
5026 u8 mgmt_err = mgmt_status(status);
5027
5028 /* We need to restore the flag if related HCI commands
5029 * failed.
5030 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005031 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005032
Johan Hedberga69e8372015-03-06 21:08:53 +02005033 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005034 } else {
5035 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
5036 new_settings(hdev, cmd->sk);
5037 }
5038
5039 mgmt_pending_remove(cmd);
5040
5041unlock:
5042 hci_dev_unlock(hdev);
5043}
5044
5045static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
5046{
5047 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005048 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03005049 struct hci_request req;
5050 int err;
5051
5052 BT_DBG("request for %s", hdev->name);
5053
5054 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005055 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5056 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005057
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005058 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005059 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5060 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005061
5062 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005063 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5064 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005065
5066 hci_dev_lock(hdev);
5067
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005068 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03005069 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5070 goto unlock;
5071 }
5072
5073 if (!hdev_is_powered(hdev)) {
5074 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005075 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
5076 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
5077 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
5078 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
5079 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005080 }
5081
Marcel Holtmannce05d602015-03-13 02:11:03 -07005082 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005083
5084 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
5085 if (err < 0)
5086 goto unlock;
5087
5088 err = new_settings(hdev, sk);
5089 goto unlock;
5090 }
5091
5092 /* Reject disabling when powered on */
5093 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005094 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5095 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005096 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005097 } else {
5098 /* When configuring a dual-mode controller to operate
5099 * with LE only and using a static address, then switching
5100 * BR/EDR back on is not allowed.
5101 *
5102 * Dual-mode controllers shall operate with the public
5103 * address as its identity address for BR/EDR and LE. So
5104 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005105 *
5106 * The same restrictions applies when secure connections
5107 * has been enabled. For BR/EDR this is a controller feature
5108 * while for LE it is a host stack feature. This means that
5109 * switching BR/EDR back on when secure connections has been
5110 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005111 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005112 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08005113 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005114 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005115 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5116 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08005117 goto unlock;
5118 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03005119 }
5120
Johan Hedberg333ae952015-03-17 13:48:47 +02005121 if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005122 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
5123 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005124 goto unlock;
5125 }
5126
5127 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
5128 if (!cmd) {
5129 err = -ENOMEM;
5130 goto unlock;
5131 }
5132
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005133 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03005134 * generates the correct flags.
5135 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005136 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03005137
5138 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005139
Johan Hedberg432df052014-08-01 11:13:31 +03005140 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02005141 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005142
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005143 /* Since only the advertising data flags will change, there
5144 * is no need to update the scan response data.
5145 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005146 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03005147
Johan Hedberg0663ca22013-10-02 13:43:14 +03005148 err = hci_req_run(&req, set_bredr_complete);
5149 if (err < 0)
5150 mgmt_pending_remove(cmd);
5151
5152unlock:
5153 hci_dev_unlock(hdev);
5154 return err;
5155}
5156
Johan Hedberga1443f52015-01-23 15:42:46 +02005157static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
5158{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005159 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005160 struct mgmt_mode *cp;
5161
5162 BT_DBG("%s status %u", hdev->name, status);
5163
5164 hci_dev_lock(hdev);
5165
Johan Hedberg333ae952015-03-17 13:48:47 +02005166 cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
Johan Hedberga1443f52015-01-23 15:42:46 +02005167 if (!cmd)
5168 goto unlock;
5169
5170 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005171 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
5172 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005173 goto remove;
5174 }
5175
5176 cp = cmd->param;
5177
5178 switch (cp->val) {
5179 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005180 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5181 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005182 break;
5183 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005184 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005185 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005186 break;
5187 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005188 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5189 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005190 break;
5191 }
5192
5193 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5194 new_settings(hdev, cmd->sk);
5195
5196remove:
5197 mgmt_pending_remove(cmd);
5198unlock:
5199 hci_dev_unlock(hdev);
5200}
5201
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005202static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5203 void *data, u16 len)
5204{
5205 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005206 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005207 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005208 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005209 int err;
5210
5211 BT_DBG("request for %s", hdev->name);
5212
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005213 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005214 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005215 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5216 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005217
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005218 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005219 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005220 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005221 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5222 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005223
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005224 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005225 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005226 MGMT_STATUS_INVALID_PARAMS);
5227
5228 hci_dev_lock(hdev);
5229
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005230 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005231 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005232 bool changed;
5233
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005234 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005235 changed = !hci_dev_test_and_set_flag(hdev,
5236 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005237 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005238 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005239 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005240 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005241 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005242 changed = hci_dev_test_and_clear_flag(hdev,
5243 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005244 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005245 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005246
5247 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5248 if (err < 0)
5249 goto failed;
5250
5251 if (changed)
5252 err = new_settings(hdev, sk);
5253
5254 goto failed;
5255 }
5256
Johan Hedberg333ae952015-03-17 13:48:47 +02005257 if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005258 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5259 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005260 goto failed;
5261 }
5262
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005263 val = !!cp->val;
5264
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005265 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5266 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005267 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5268 goto failed;
5269 }
5270
5271 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5272 if (!cmd) {
5273 err = -ENOMEM;
5274 goto failed;
5275 }
5276
Johan Hedberga1443f52015-01-23 15:42:46 +02005277 hci_req_init(&req, hdev);
5278 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5279 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005280 if (err < 0) {
5281 mgmt_pending_remove(cmd);
5282 goto failed;
5283 }
5284
5285failed:
5286 hci_dev_unlock(hdev);
5287 return err;
5288}
5289
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005290static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5291 void *data, u16 len)
5292{
5293 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005294 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005295 int err;
5296
5297 BT_DBG("request for %s", hdev->name);
5298
Johan Hedbergb97109792014-06-24 14:00:28 +03005299 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005300 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5301 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005302
5303 hci_dev_lock(hdev);
5304
5305 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005306 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005307 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005308 changed = hci_dev_test_and_clear_flag(hdev,
5309 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005310
Johan Hedbergb97109792014-06-24 14:00:28 +03005311 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005312 use_changed = !hci_dev_test_and_set_flag(hdev,
5313 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005314 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005315 use_changed = hci_dev_test_and_clear_flag(hdev,
5316 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005317
5318 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005319 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005320 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5321 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5322 sizeof(mode), &mode);
5323 }
5324
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005325 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5326 if (err < 0)
5327 goto unlock;
5328
5329 if (changed)
5330 err = new_settings(hdev, sk);
5331
5332unlock:
5333 hci_dev_unlock(hdev);
5334 return err;
5335}
5336
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005337static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5338 u16 len)
5339{
5340 struct mgmt_cp_set_privacy *cp = cp_data;
5341 bool changed;
5342 int err;
5343
5344 BT_DBG("request for %s", hdev->name);
5345
5346 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005347 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5348 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005349
5350 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005351 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5352 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005353
5354 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005355 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5356 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005357
5358 hci_dev_lock(hdev);
5359
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005360 /* If user space supports this command it is also expected to
5361 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5362 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005363 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005364
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005365 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005366 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005367 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005368 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005369 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005370 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005371 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005372 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005373 }
5374
5375 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5376 if (err < 0)
5377 goto unlock;
5378
5379 if (changed)
5380 err = new_settings(hdev, sk);
5381
5382unlock:
5383 hci_dev_unlock(hdev);
5384 return err;
5385}
5386
Johan Hedberg41edf162014-02-18 10:19:35 +02005387static bool irk_is_valid(struct mgmt_irk_info *irk)
5388{
5389 switch (irk->addr.type) {
5390 case BDADDR_LE_PUBLIC:
5391 return true;
5392
5393 case BDADDR_LE_RANDOM:
5394 /* Two most significant bits shall be set */
5395 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5396 return false;
5397 return true;
5398 }
5399
5400 return false;
5401}
5402
5403static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5404 u16 len)
5405{
5406 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005407 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5408 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005409 u16 irk_count, expected_len;
5410 int i, err;
5411
5412 BT_DBG("request for %s", hdev->name);
5413
5414 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005415 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5416 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005417
5418 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005419 if (irk_count > max_irk_count) {
5420 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005421 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5422 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005423 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005424
5425 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5426 if (expected_len != len) {
5427 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005428 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005429 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5430 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005431 }
5432
5433 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5434
5435 for (i = 0; i < irk_count; i++) {
5436 struct mgmt_irk_info *key = &cp->irks[i];
5437
5438 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005439 return mgmt_cmd_status(sk, hdev->id,
5440 MGMT_OP_LOAD_IRKS,
5441 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005442 }
5443
5444 hci_dev_lock(hdev);
5445
5446 hci_smp_irks_clear(hdev);
5447
5448 for (i = 0; i < irk_count; i++) {
5449 struct mgmt_irk_info *irk = &cp->irks[i];
5450 u8 addr_type;
5451
5452 if (irk->addr.type == BDADDR_LE_PUBLIC)
5453 addr_type = ADDR_LE_DEV_PUBLIC;
5454 else
5455 addr_type = ADDR_LE_DEV_RANDOM;
5456
5457 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5458 BDADDR_ANY);
5459 }
5460
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005461 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005462
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005463 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005464
5465 hci_dev_unlock(hdev);
5466
5467 return err;
5468}
5469
Johan Hedberg3f706b72013-01-20 14:27:16 +02005470static bool ltk_is_valid(struct mgmt_ltk_info *key)
5471{
5472 if (key->master != 0x00 && key->master != 0x01)
5473 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005474
5475 switch (key->addr.type) {
5476 case BDADDR_LE_PUBLIC:
5477 return true;
5478
5479 case BDADDR_LE_RANDOM:
5480 /* Two most significant bits shall be set */
5481 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5482 return false;
5483 return true;
5484 }
5485
5486 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005487}
5488
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005489static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005490 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005491{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005492 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005493 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5494 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005495 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005496 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005497
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005498 BT_DBG("request for %s", hdev->name);
5499
5500 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005501 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5502 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005503
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005504 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005505 if (key_count > max_key_count) {
5506 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005507 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5508 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005509 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005510
5511 expected_len = sizeof(*cp) + key_count *
5512 sizeof(struct mgmt_ltk_info);
5513 if (expected_len != len) {
5514 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005515 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005516 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5517 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005518 }
5519
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005520 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005521
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005522 for (i = 0; i < key_count; i++) {
5523 struct mgmt_ltk_info *key = &cp->keys[i];
5524
Johan Hedberg3f706b72013-01-20 14:27:16 +02005525 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005526 return mgmt_cmd_status(sk, hdev->id,
5527 MGMT_OP_LOAD_LONG_TERM_KEYS,
5528 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005529 }
5530
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005531 hci_dev_lock(hdev);
5532
5533 hci_smp_ltks_clear(hdev);
5534
5535 for (i = 0; i < key_count; i++) {
5536 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005537 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005538
5539 if (key->addr.type == BDADDR_LE_PUBLIC)
5540 addr_type = ADDR_LE_DEV_PUBLIC;
5541 else
5542 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005543
Johan Hedberg61b43352014-05-29 19:36:53 +03005544 switch (key->type) {
5545 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005546 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005547 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005548 break;
5549 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005550 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005551 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005552 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005553 case MGMT_LTK_P256_UNAUTH:
5554 authenticated = 0x00;
5555 type = SMP_LTK_P256;
5556 break;
5557 case MGMT_LTK_P256_AUTH:
5558 authenticated = 0x01;
5559 type = SMP_LTK_P256;
5560 break;
5561 case MGMT_LTK_P256_DEBUG:
5562 authenticated = 0x00;
5563 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005564 default:
5565 continue;
5566 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005567
Johan Hedberg35d70272014-02-19 14:57:47 +02005568 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005569 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005570 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005571 }
5572
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005573 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005574 NULL, 0);
5575
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005576 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005577
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005578 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005579}
5580
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005581static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005582{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005583 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005584 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005585 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005586
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005587 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005588
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005589 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005590 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005591 rp.tx_power = conn->tx_power;
5592 rp.max_tx_power = conn->max_tx_power;
5593 } else {
5594 rp.rssi = HCI_RSSI_INVALID;
5595 rp.tx_power = HCI_TX_POWER_INVALID;
5596 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005597 }
5598
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005599 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5600 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005601
5602 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005603 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005604
5605 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005606}
5607
Marcel Holtmann1904a852015-01-11 13:50:44 -08005608static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5609 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005610{
5611 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005612 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005613 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005614 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005615 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005616
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005617 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005618
5619 hci_dev_lock(hdev);
5620
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005621 /* Commands sent in request are either Read RSSI or Read Transmit Power
5622 * Level so we check which one was last sent to retrieve connection
5623 * handle. Both commands have handle as first parameter so it's safe to
5624 * cast data on the same command struct.
5625 *
5626 * First command sent is always Read RSSI and we fail only if it fails.
5627 * In other case we simply override error to indicate success as we
5628 * already remembered if TX power value is actually valid.
5629 */
5630 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5631 if (!cp) {
5632 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005633 status = MGMT_STATUS_SUCCESS;
5634 } else {
5635 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005636 }
5637
5638 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005639 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005640 goto unlock;
5641 }
5642
5643 handle = __le16_to_cpu(cp->handle);
5644 conn = hci_conn_hash_lookup_handle(hdev, handle);
5645 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005646 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005647 goto unlock;
5648 }
5649
Johan Hedberg333ae952015-03-17 13:48:47 +02005650 cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005651 if (!cmd)
5652 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005653
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005654 cmd->cmd_complete(cmd, status);
5655 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005656
5657unlock:
5658 hci_dev_unlock(hdev);
5659}
5660
5661static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5662 u16 len)
5663{
5664 struct mgmt_cp_get_conn_info *cp = data;
5665 struct mgmt_rp_get_conn_info rp;
5666 struct hci_conn *conn;
5667 unsigned long conn_info_age;
5668 int err = 0;
5669
5670 BT_DBG("%s", hdev->name);
5671
5672 memset(&rp, 0, sizeof(rp));
5673 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5674 rp.addr.type = cp->addr.type;
5675
5676 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005677 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5678 MGMT_STATUS_INVALID_PARAMS,
5679 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005680
5681 hci_dev_lock(hdev);
5682
5683 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005684 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5685 MGMT_STATUS_NOT_POWERED, &rp,
5686 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005687 goto unlock;
5688 }
5689
5690 if (cp->addr.type == BDADDR_BREDR)
5691 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5692 &cp->addr.bdaddr);
5693 else
5694 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5695
5696 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005697 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5698 MGMT_STATUS_NOT_CONNECTED, &rp,
5699 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005700 goto unlock;
5701 }
5702
Johan Hedberg333ae952015-03-17 13:48:47 +02005703 if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005704 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5705 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005706 goto unlock;
5707 }
5708
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005709 /* To avoid client trying to guess when to poll again for information we
5710 * calculate conn info age as random value between min/max set in hdev.
5711 */
5712 conn_info_age = hdev->conn_info_min_age +
5713 prandom_u32_max(hdev->conn_info_max_age -
5714 hdev->conn_info_min_age);
5715
5716 /* Query controller to refresh cached values if they are too old or were
5717 * never read.
5718 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005719 if (time_after(jiffies, conn->conn_info_timestamp +
5720 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005721 !conn->conn_info_timestamp) {
5722 struct hci_request req;
5723 struct hci_cp_read_tx_power req_txp_cp;
5724 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005725 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005726
5727 hci_req_init(&req, hdev);
5728 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5729 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5730 &req_rssi_cp);
5731
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005732 /* For LE links TX power does not change thus we don't need to
5733 * query for it once value is known.
5734 */
5735 if (!bdaddr_type_is_le(cp->addr.type) ||
5736 conn->tx_power == HCI_TX_POWER_INVALID) {
5737 req_txp_cp.handle = cpu_to_le16(conn->handle);
5738 req_txp_cp.type = 0x00;
5739 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5740 sizeof(req_txp_cp), &req_txp_cp);
5741 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005742
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005743 /* Max TX power needs to be read only once per connection */
5744 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5745 req_txp_cp.handle = cpu_to_le16(conn->handle);
5746 req_txp_cp.type = 0x01;
5747 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5748 sizeof(req_txp_cp), &req_txp_cp);
5749 }
5750
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005751 err = hci_req_run(&req, conn_info_refresh_complete);
5752 if (err < 0)
5753 goto unlock;
5754
5755 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5756 data, len);
5757 if (!cmd) {
5758 err = -ENOMEM;
5759 goto unlock;
5760 }
5761
5762 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005763 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005764 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005765
5766 conn->conn_info_timestamp = jiffies;
5767 } else {
5768 /* Cache is valid, just reply with values cached in hci_conn */
5769 rp.rssi = conn->rssi;
5770 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005771 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005772
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005773 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5774 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005775 }
5776
5777unlock:
5778 hci_dev_unlock(hdev);
5779 return err;
5780}
5781
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005782static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005783{
5784 struct hci_conn *conn = cmd->user_data;
5785 struct mgmt_rp_get_clock_info rp;
5786 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005787 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005788
5789 memset(&rp, 0, sizeof(rp));
5790 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5791
5792 if (status)
5793 goto complete;
5794
5795 hdev = hci_dev_get(cmd->index);
5796 if (hdev) {
5797 rp.local_clock = cpu_to_le32(hdev->clock);
5798 hci_dev_put(hdev);
5799 }
5800
5801 if (conn) {
5802 rp.piconet_clock = cpu_to_le32(conn->clock);
5803 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5804 }
5805
5806complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005807 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5808 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005809
5810 if (conn) {
5811 hci_conn_drop(conn);
5812 hci_conn_put(conn);
5813 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005814
5815 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005816}
5817
Marcel Holtmann1904a852015-01-11 13:50:44 -08005818static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005819{
Johan Hedberg95868422014-06-28 17:54:07 +03005820 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005821 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005822 struct hci_conn *conn;
5823
5824 BT_DBG("%s status %u", hdev->name, status);
5825
5826 hci_dev_lock(hdev);
5827
5828 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5829 if (!hci_cp)
5830 goto unlock;
5831
5832 if (hci_cp->which) {
5833 u16 handle = __le16_to_cpu(hci_cp->handle);
5834 conn = hci_conn_hash_lookup_handle(hdev, handle);
5835 } else {
5836 conn = NULL;
5837 }
5838
Johan Hedberg333ae952015-03-17 13:48:47 +02005839 cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005840 if (!cmd)
5841 goto unlock;
5842
Johan Hedberg69487372014-12-05 13:36:07 +02005843 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005844 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005845
5846unlock:
5847 hci_dev_unlock(hdev);
5848}
5849
5850static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5851 u16 len)
5852{
5853 struct mgmt_cp_get_clock_info *cp = data;
5854 struct mgmt_rp_get_clock_info rp;
5855 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005856 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005857 struct hci_request req;
5858 struct hci_conn *conn;
5859 int err;
5860
5861 BT_DBG("%s", hdev->name);
5862
5863 memset(&rp, 0, sizeof(rp));
5864 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5865 rp.addr.type = cp->addr.type;
5866
5867 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005868 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5869 MGMT_STATUS_INVALID_PARAMS,
5870 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005871
5872 hci_dev_lock(hdev);
5873
5874 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005875 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5876 MGMT_STATUS_NOT_POWERED, &rp,
5877 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005878 goto unlock;
5879 }
5880
5881 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5882 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5883 &cp->addr.bdaddr);
5884 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005885 err = mgmt_cmd_complete(sk, hdev->id,
5886 MGMT_OP_GET_CLOCK_INFO,
5887 MGMT_STATUS_NOT_CONNECTED,
5888 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005889 goto unlock;
5890 }
5891 } else {
5892 conn = NULL;
5893 }
5894
5895 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5896 if (!cmd) {
5897 err = -ENOMEM;
5898 goto unlock;
5899 }
5900
Johan Hedberg69487372014-12-05 13:36:07 +02005901 cmd->cmd_complete = clock_info_cmd_complete;
5902
Johan Hedberg95868422014-06-28 17:54:07 +03005903 hci_req_init(&req, hdev);
5904
5905 memset(&hci_cp, 0, sizeof(hci_cp));
5906 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5907
5908 if (conn) {
5909 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005910 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005911
5912 hci_cp.handle = cpu_to_le16(conn->handle);
5913 hci_cp.which = 0x01; /* Piconet clock */
5914 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5915 }
5916
5917 err = hci_req_run(&req, get_clock_info_complete);
5918 if (err < 0)
5919 mgmt_pending_remove(cmd);
5920
5921unlock:
5922 hci_dev_unlock(hdev);
5923 return err;
5924}
5925
Johan Hedberg5a154e62014-12-19 22:26:02 +02005926static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5927{
5928 struct hci_conn *conn;
5929
5930 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5931 if (!conn)
5932 return false;
5933
5934 if (conn->dst_type != type)
5935 return false;
5936
5937 if (conn->state != BT_CONNECTED)
5938 return false;
5939
5940 return true;
5941}
5942
5943/* This function requires the caller holds hdev->lock */
5944static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5945 u8 addr_type, u8 auto_connect)
5946{
5947 struct hci_dev *hdev = req->hdev;
5948 struct hci_conn_params *params;
5949
5950 params = hci_conn_params_add(hdev, addr, addr_type);
5951 if (!params)
5952 return -EIO;
5953
5954 if (params->auto_connect == auto_connect)
5955 return 0;
5956
5957 list_del_init(&params->action);
5958
5959 switch (auto_connect) {
5960 case HCI_AUTO_CONN_DISABLED:
5961 case HCI_AUTO_CONN_LINK_LOSS:
5962 __hci_update_background_scan(req);
5963 break;
5964 case HCI_AUTO_CONN_REPORT:
5965 list_add(&params->action, &hdev->pend_le_reports);
5966 __hci_update_background_scan(req);
5967 break;
5968 case HCI_AUTO_CONN_DIRECT:
5969 case HCI_AUTO_CONN_ALWAYS:
5970 if (!is_connected(hdev, addr, addr_type)) {
5971 list_add(&params->action, &hdev->pend_le_conns);
5972 __hci_update_background_scan(req);
5973 }
5974 break;
5975 }
5976
5977 params->auto_connect = auto_connect;
5978
5979 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5980 auto_connect);
5981
5982 return 0;
5983}
5984
Marcel Holtmann8afef092014-06-29 22:28:34 +02005985static void device_added(struct sock *sk, struct hci_dev *hdev,
5986 bdaddr_t *bdaddr, u8 type, u8 action)
5987{
5988 struct mgmt_ev_device_added ev;
5989
5990 bacpy(&ev.addr.bdaddr, bdaddr);
5991 ev.addr.type = type;
5992 ev.action = action;
5993
5994 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5995}
5996
Marcel Holtmann1904a852015-01-11 13:50:44 -08005997static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005998{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005999 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006000
6001 BT_DBG("status 0x%02x", status);
6002
6003 hci_dev_lock(hdev);
6004
Johan Hedberg333ae952015-03-17 13:48:47 +02006005 cmd = pending_find(MGMT_OP_ADD_DEVICE, hdev);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006006 if (!cmd)
6007 goto unlock;
6008
6009 cmd->cmd_complete(cmd, mgmt_status(status));
6010 mgmt_pending_remove(cmd);
6011
6012unlock:
6013 hci_dev_unlock(hdev);
6014}
6015
Marcel Holtmann2faade52014-06-29 19:44:03 +02006016static int add_device(struct sock *sk, struct hci_dev *hdev,
6017 void *data, u16 len)
6018{
6019 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006020 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02006021 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006022 u8 auto_conn, addr_type;
6023 int err;
6024
6025 BT_DBG("%s", hdev->name);
6026
Johan Hedberg66593582014-07-09 12:59:14 +03006027 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02006028 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006029 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6030 MGMT_STATUS_INVALID_PARAMS,
6031 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006032
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006033 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006034 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
6035 MGMT_STATUS_INVALID_PARAMS,
6036 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02006037
Johan Hedberg5a154e62014-12-19 22:26:02 +02006038 hci_req_init(&req, hdev);
6039
Marcel Holtmann2faade52014-06-29 19:44:03 +02006040 hci_dev_lock(hdev);
6041
Johan Hedberg5a154e62014-12-19 22:26:02 +02006042 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
6043 if (!cmd) {
6044 err = -ENOMEM;
6045 goto unlock;
6046 }
6047
6048 cmd->cmd_complete = addr_cmd_complete;
6049
Johan Hedberg66593582014-07-09 12:59:14 +03006050 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006051 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03006052 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006053 err = cmd->cmd_complete(cmd,
6054 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006055 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006056 goto unlock;
6057 }
6058
6059 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
6060 cp->addr.type);
6061 if (err)
6062 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03006063
Johan Hedberg5a154e62014-12-19 22:26:02 +02006064 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006065
Johan Hedberg66593582014-07-09 12:59:14 +03006066 goto added;
6067 }
6068
Marcel Holtmann2faade52014-06-29 19:44:03 +02006069 if (cp->addr.type == BDADDR_LE_PUBLIC)
6070 addr_type = ADDR_LE_DEV_PUBLIC;
6071 else
6072 addr_type = ADDR_LE_DEV_RANDOM;
6073
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006074 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02006075 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006076 else if (cp->action == 0x01)
6077 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006078 else
Johan Hedberga3451d22014-07-02 17:37:27 +03006079 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006080
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02006081 /* If the connection parameters don't exist for this device,
6082 * they will be created and configured with defaults.
6083 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02006084 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02006085 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006086 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006087 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006088 goto unlock;
6089 }
6090
Johan Hedberg66593582014-07-09 12:59:14 +03006091added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02006092 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
6093
Johan Hedberg5a154e62014-12-19 22:26:02 +02006094 err = hci_req_run(&req, add_device_complete);
6095 if (err < 0) {
6096 /* ENODATA means no HCI commands were needed (e.g. if
6097 * the adapter is powered off).
6098 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006099 if (err == -ENODATA)
6100 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02006101 mgmt_pending_remove(cmd);
6102 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006103
6104unlock:
6105 hci_dev_unlock(hdev);
6106 return err;
6107}
6108
Marcel Holtmann8afef092014-06-29 22:28:34 +02006109static void device_removed(struct sock *sk, struct hci_dev *hdev,
6110 bdaddr_t *bdaddr, u8 type)
6111{
6112 struct mgmt_ev_device_removed ev;
6113
6114 bacpy(&ev.addr.bdaddr, bdaddr);
6115 ev.addr.type = type;
6116
6117 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
6118}
6119
Marcel Holtmann1904a852015-01-11 13:50:44 -08006120static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006121{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006122 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006123
6124 BT_DBG("status 0x%02x", status);
6125
6126 hci_dev_lock(hdev);
6127
Johan Hedberg333ae952015-03-17 13:48:47 +02006128 cmd = pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006129 if (!cmd)
6130 goto unlock;
6131
6132 cmd->cmd_complete(cmd, mgmt_status(status));
6133 mgmt_pending_remove(cmd);
6134
6135unlock:
6136 hci_dev_unlock(hdev);
6137}
6138
Marcel Holtmann2faade52014-06-29 19:44:03 +02006139static int remove_device(struct sock *sk, struct hci_dev *hdev,
6140 void *data, u16 len)
6141{
6142 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006143 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006144 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006145 int err;
6146
6147 BT_DBG("%s", hdev->name);
6148
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006149 hci_req_init(&req, hdev);
6150
Marcel Holtmann2faade52014-06-29 19:44:03 +02006151 hci_dev_lock(hdev);
6152
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006153 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
6154 if (!cmd) {
6155 err = -ENOMEM;
6156 goto unlock;
6157 }
6158
6159 cmd->cmd_complete = addr_cmd_complete;
6160
Marcel Holtmann2faade52014-06-29 19:44:03 +02006161 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03006162 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02006163 u8 addr_type;
6164
Johan Hedberg66593582014-07-09 12:59:14 +03006165 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006166 err = cmd->cmd_complete(cmd,
6167 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006168 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006169 goto unlock;
6170 }
6171
Johan Hedberg66593582014-07-09 12:59:14 +03006172 if (cp->addr.type == BDADDR_BREDR) {
6173 err = hci_bdaddr_list_del(&hdev->whitelist,
6174 &cp->addr.bdaddr,
6175 cp->addr.type);
6176 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006177 err = cmd->cmd_complete(cmd,
6178 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006179 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006180 goto unlock;
6181 }
6182
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006183 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006184
Johan Hedberg66593582014-07-09 12:59:14 +03006185 device_removed(sk, hdev, &cp->addr.bdaddr,
6186 cp->addr.type);
6187 goto complete;
6188 }
6189
Marcel Holtmann2faade52014-06-29 19:44:03 +02006190 if (cp->addr.type == BDADDR_LE_PUBLIC)
6191 addr_type = ADDR_LE_DEV_PUBLIC;
6192 else
6193 addr_type = ADDR_LE_DEV_RANDOM;
6194
Johan Hedbergc71593d2014-07-02 17:37:28 +03006195 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6196 addr_type);
6197 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006198 err = cmd->cmd_complete(cmd,
6199 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006200 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006201 goto unlock;
6202 }
6203
6204 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006205 err = cmd->cmd_complete(cmd,
6206 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006207 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006208 goto unlock;
6209 }
6210
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006211 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006212 list_del(&params->list);
6213 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006214 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006215
6216 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006217 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006218 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006219 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006220
Marcel Holtmann2faade52014-06-29 19:44:03 +02006221 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006222 err = cmd->cmd_complete(cmd,
6223 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006224 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006225 goto unlock;
6226 }
6227
Johan Hedberg66593582014-07-09 12:59:14 +03006228 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6229 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6230 list_del(&b->list);
6231 kfree(b);
6232 }
6233
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006234 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006235
Johan Hedberg19de0822014-07-06 13:06:51 +03006236 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6237 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6238 continue;
6239 device_removed(sk, hdev, &p->addr, p->addr_type);
6240 list_del(&p->action);
6241 list_del(&p->list);
6242 kfree(p);
6243 }
6244
6245 BT_DBG("All LE connection parameters were removed");
6246
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006247 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006248 }
6249
Johan Hedberg66593582014-07-09 12:59:14 +03006250complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006251 err = hci_req_run(&req, remove_device_complete);
6252 if (err < 0) {
6253 /* ENODATA means no HCI commands were needed (e.g. if
6254 * the adapter is powered off).
6255 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006256 if (err == -ENODATA)
6257 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006258 mgmt_pending_remove(cmd);
6259 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006260
6261unlock:
6262 hci_dev_unlock(hdev);
6263 return err;
6264}
6265
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006266static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6267 u16 len)
6268{
6269 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006270 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6271 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006272 u16 param_count, expected_len;
6273 int i;
6274
6275 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006276 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6277 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006278
6279 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006280 if (param_count > max_param_count) {
6281 BT_ERR("load_conn_param: too big param_count value %u",
6282 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006283 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6284 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006285 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006286
6287 expected_len = sizeof(*cp) + param_count *
6288 sizeof(struct mgmt_conn_param);
6289 if (expected_len != len) {
6290 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6291 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006292 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6293 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006294 }
6295
6296 BT_DBG("%s param_count %u", hdev->name, param_count);
6297
6298 hci_dev_lock(hdev);
6299
6300 hci_conn_params_clear_disabled(hdev);
6301
6302 for (i = 0; i < param_count; i++) {
6303 struct mgmt_conn_param *param = &cp->params[i];
6304 struct hci_conn_params *hci_param;
6305 u16 min, max, latency, timeout;
6306 u8 addr_type;
6307
6308 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6309 param->addr.type);
6310
6311 if (param->addr.type == BDADDR_LE_PUBLIC) {
6312 addr_type = ADDR_LE_DEV_PUBLIC;
6313 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6314 addr_type = ADDR_LE_DEV_RANDOM;
6315 } else {
6316 BT_ERR("Ignoring invalid connection parameters");
6317 continue;
6318 }
6319
6320 min = le16_to_cpu(param->min_interval);
6321 max = le16_to_cpu(param->max_interval);
6322 latency = le16_to_cpu(param->latency);
6323 timeout = le16_to_cpu(param->timeout);
6324
6325 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6326 min, max, latency, timeout);
6327
6328 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6329 BT_ERR("Ignoring invalid connection parameters");
6330 continue;
6331 }
6332
6333 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6334 addr_type);
6335 if (!hci_param) {
6336 BT_ERR("Failed to add connection parameters");
6337 continue;
6338 }
6339
6340 hci_param->conn_min_interval = min;
6341 hci_param->conn_max_interval = max;
6342 hci_param->conn_latency = latency;
6343 hci_param->supervision_timeout = timeout;
6344 }
6345
6346 hci_dev_unlock(hdev);
6347
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006348 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6349 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006350}
6351
Marcel Holtmanndbece372014-07-04 18:11:55 +02006352static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6353 void *data, u16 len)
6354{
6355 struct mgmt_cp_set_external_config *cp = data;
6356 bool changed;
6357 int err;
6358
6359 BT_DBG("%s", hdev->name);
6360
6361 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006362 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6363 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006364
6365 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006366 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6367 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006368
6369 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006370 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6371 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006372
6373 hci_dev_lock(hdev);
6374
6375 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006376 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006377 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006378 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006379
6380 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6381 if (err < 0)
6382 goto unlock;
6383
6384 if (!changed)
6385 goto unlock;
6386
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006387 err = new_options(hdev, sk);
6388
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006389 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006390 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006391
Marcel Holtmann516018a2015-03-13 02:11:04 -07006392 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006393 hci_dev_set_flag(hdev, HCI_CONFIG);
6394 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006395
6396 queue_work(hdev->req_workqueue, &hdev->power_on);
6397 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006398 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006399 mgmt_index_added(hdev);
6400 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006401 }
6402
6403unlock:
6404 hci_dev_unlock(hdev);
6405 return err;
6406}
6407
Marcel Holtmann9713c172014-07-06 12:11:15 +02006408static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6409 void *data, u16 len)
6410{
6411 struct mgmt_cp_set_public_address *cp = data;
6412 bool changed;
6413 int err;
6414
6415 BT_DBG("%s", hdev->name);
6416
6417 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006418 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6419 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006420
6421 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006422 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6423 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006424
6425 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006426 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6427 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006428
6429 hci_dev_lock(hdev);
6430
6431 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6432 bacpy(&hdev->public_addr, &cp->bdaddr);
6433
6434 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6435 if (err < 0)
6436 goto unlock;
6437
6438 if (!changed)
6439 goto unlock;
6440
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006441 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006442 err = new_options(hdev, sk);
6443
6444 if (is_configured(hdev)) {
6445 mgmt_index_removed(hdev);
6446
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006447 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006448
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006449 hci_dev_set_flag(hdev, HCI_CONFIG);
6450 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006451
6452 queue_work(hdev->req_workqueue, &hdev->power_on);
6453 }
6454
6455unlock:
6456 hci_dev_unlock(hdev);
6457 return err;
6458}
6459
Marcel Holtmannbea41602015-03-14 22:43:17 -07006460static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6461 u8 data_len)
6462{
6463 eir[eir_len++] = sizeof(type) + data_len;
6464 eir[eir_len++] = type;
6465 memcpy(&eir[eir_len], data, data_len);
6466 eir_len += data_len;
6467
6468 return eir_len;
6469}
6470
Johan Hedberg40f66c02015-04-07 21:52:22 +03006471static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
6472 u16 opcode, struct sk_buff *skb)
6473{
6474 const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
6475 struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
6476 u8 *h192, *r192, *h256, *r256;
6477 struct mgmt_pending_cmd *cmd;
6478 u16 eir_len;
6479 int err;
6480
6481 BT_DBG("%s status %u", hdev->name, status);
6482
6483 cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
6484 if (!cmd)
6485 return;
6486
6487 mgmt_cp = cmd->param;
6488
6489 if (status) {
6490 status = mgmt_status(status);
6491 eir_len = 0;
6492
6493 h192 = NULL;
6494 r192 = NULL;
6495 h256 = NULL;
6496 r256 = NULL;
6497 } else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
6498 struct hci_rp_read_local_oob_data *rp;
6499
6500 if (skb->len != sizeof(*rp)) {
6501 status = MGMT_STATUS_FAILED;
6502 eir_len = 0;
6503 } else {
6504 status = MGMT_STATUS_SUCCESS;
6505 rp = (void *)skb->data;
6506
6507 eir_len = 5 + 18 + 18;
6508 h192 = rp->hash;
6509 r192 = rp->rand;
6510 h256 = NULL;
6511 r256 = NULL;
6512 }
6513 } else {
6514 struct hci_rp_read_local_oob_ext_data *rp;
6515
6516 if (skb->len != sizeof(*rp)) {
6517 status = MGMT_STATUS_FAILED;
6518 eir_len = 0;
6519 } else {
6520 status = MGMT_STATUS_SUCCESS;
6521 rp = (void *)skb->data;
6522
6523 if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
6524 eir_len = 5 + 18 + 18;
6525 h192 = NULL;
6526 r192 = NULL;
6527 } else {
6528 eir_len = 5 + 18 + 18 + 18 + 18;
6529 h192 = rp->hash192;
6530 r192 = rp->rand192;
6531 }
6532
6533 h256 = rp->hash256;
6534 r256 = rp->rand256;
6535 }
6536 }
6537
6538 mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
6539 if (!mgmt_rp)
6540 goto done;
6541
6542 if (status)
6543 goto send_rsp;
6544
6545 eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
6546 hdev->dev_class, 3);
6547
6548 if (h192 && r192) {
6549 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6550 EIR_SSP_HASH_C192, h192, 16);
6551 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6552 EIR_SSP_RAND_R192, r192, 16);
6553 }
6554
6555 if (h256 && r256) {
6556 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6557 EIR_SSP_HASH_C256, h256, 16);
6558 eir_len = eir_append_data(mgmt_rp->eir, eir_len,
6559 EIR_SSP_RAND_R256, r256, 16);
6560 }
6561
6562send_rsp:
6563 mgmt_rp->type = mgmt_cp->type;
6564 mgmt_rp->eir_len = cpu_to_le16(eir_len);
6565
6566 err = mgmt_cmd_complete(cmd->sk, hdev->id,
6567 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
6568 mgmt_rp, sizeof(*mgmt_rp) + eir_len);
6569 if (err < 0 || status)
6570 goto done;
6571
6572 hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
6573
6574 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6575 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
6576 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
6577done:
6578 kfree(mgmt_rp);
6579 mgmt_pending_remove(cmd);
6580}
6581
6582static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
6583 struct mgmt_cp_read_local_oob_ext_data *cp)
6584{
6585 struct mgmt_pending_cmd *cmd;
6586 struct hci_request req;
6587 int err;
6588
6589 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
6590 cp, sizeof(*cp));
6591 if (!cmd)
6592 return -ENOMEM;
6593
6594 hci_req_init(&req, hdev);
6595
6596 if (bredr_sc_enabled(hdev))
6597 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
6598 else
6599 hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
6600
6601 err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
6602 if (err < 0) {
6603 mgmt_pending_remove(cmd);
6604 return err;
6605 }
6606
6607 return 0;
6608}
6609
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006610static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6611 void *data, u16 data_len)
6612{
6613 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6614 struct mgmt_rp_read_local_oob_ext_data *rp;
6615 size_t rp_len;
6616 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006617 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006618 int err;
6619
6620 BT_DBG("%s", hdev->name);
6621
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006622 if (hdev_is_powered(hdev)) {
6623 switch (cp->type) {
6624 case BIT(BDADDR_BREDR):
6625 status = mgmt_bredr_support(hdev);
6626 if (status)
6627 eir_len = 0;
6628 else
6629 eir_len = 5;
6630 break;
6631 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6632 status = mgmt_le_support(hdev);
6633 if (status)
6634 eir_len = 0;
6635 else
6636 eir_len = 9 + 3 + 18 + 18 + 3;
6637 break;
6638 default:
6639 status = MGMT_STATUS_INVALID_PARAMS;
6640 eir_len = 0;
6641 break;
6642 }
6643 } else {
6644 status = MGMT_STATUS_NOT_POWERED;
6645 eir_len = 0;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006646 }
6647
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006648 rp_len = sizeof(*rp) + eir_len;
6649 rp = kmalloc(rp_len, GFP_ATOMIC);
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006650 if (!rp)
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006651 return -ENOMEM;
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006652
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006653 if (status)
6654 goto complete;
6655
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006656 hci_dev_lock(hdev);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006657
6658 eir_len = 0;
6659 switch (cp->type) {
6660 case BIT(BDADDR_BREDR):
Johan Hedberg40f66c02015-04-07 21:52:22 +03006661 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
6662 err = read_local_ssp_oob_req(hdev, sk, cp);
6663 hci_dev_unlock(hdev);
6664 if (!err)
6665 goto done;
6666
6667 status = MGMT_STATUS_FAILED;
6668 goto complete;
6669 } else {
6670 eir_len = eir_append_data(rp->eir, eir_len,
6671 EIR_CLASS_OF_DEV,
6672 hdev->dev_class, 3);
6673 }
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006674 break;
6675 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006676 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6677 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006678 hci_dev_unlock(hdev);
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006679 status = MGMT_STATUS_FAILED;
6680 goto complete;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006681 }
6682
Marcel Holtmanne2135682015-04-02 12:00:58 -07006683 /* This should return the active RPA, but since the RPA
6684 * is only programmed on demand, it is really hard to fill
6685 * this in at the moment. For now disallow retrieving
6686 * local out-of-band data when privacy is in use.
6687 *
6688 * Returning the identity address will not help here since
6689 * pairing happens before the identity resolving key is
6690 * known and thus the connection establishment happens
6691 * based on the RPA and not the identity address.
6692 */
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006693 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
Marcel Holtmanne2135682015-04-02 12:00:58 -07006694 hci_dev_unlock(hdev);
6695 status = MGMT_STATUS_REJECTED;
6696 goto complete;
6697 }
6698
6699 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6700 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6701 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6702 bacmp(&hdev->static_addr, BDADDR_ANY))) {
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006703 memcpy(addr, &hdev->static_addr, 6);
6704 addr[6] = 0x01;
6705 } else {
6706 memcpy(addr, &hdev->bdaddr, 6);
6707 addr[6] = 0x00;
6708 }
6709
6710 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6711 addr, sizeof(addr));
6712
6713 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6714 role = 0x02;
6715 else
6716 role = 0x01;
6717
6718 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6719 &role, sizeof(role));
6720
Marcel Holtmann5082a592015-03-16 12:39:00 -07006721 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6722 eir_len = eir_append_data(rp->eir, eir_len,
6723 EIR_LE_SC_CONFIRM,
6724 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006725
Marcel Holtmann5082a592015-03-16 12:39:00 -07006726 eir_len = eir_append_data(rp->eir, eir_len,
6727 EIR_LE_SC_RANDOM,
6728 rand, sizeof(rand));
6729 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006730
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006731 flags = get_adv_discov_flags(hdev);
6732
6733 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6734 flags |= LE_AD_NO_BREDR;
6735
6736 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6737 &flags, sizeof(flags));
6738 break;
6739 }
6740
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006741 hci_dev_unlock(hdev);
6742
Marcel Holtmann72000df2015-03-16 16:11:21 -07006743 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6744
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006745 status = MGMT_STATUS_SUCCESS;
6746
6747complete:
Marcel Holtmannefcd8c92015-03-28 15:18:58 -07006748 rp->type = cp->type;
6749 rp->eir_len = cpu_to_le16(eir_len);
6750
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006751 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann57b0d3e2015-03-28 15:18:59 -07006752 status, rp, sizeof(*rp) + eir_len);
6753 if (err < 0 || status)
Marcel Holtmann72000df2015-03-16 16:11:21 -07006754 goto done;
6755
6756 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6757 rp, sizeof(*rp) + eir_len,
6758 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006759
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006760done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006761 kfree(rp);
6762
6763 return err;
6764}
6765
Arman Uguray089fa8c2015-03-25 18:53:45 -07006766static u32 get_supported_adv_flags(struct hci_dev *hdev)
6767{
6768 u32 flags = 0;
6769
6770 flags |= MGMT_ADV_FLAG_CONNECTABLE;
6771 flags |= MGMT_ADV_FLAG_DISCOV;
6772 flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
6773 flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
6774
6775 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
6776 flags |= MGMT_ADV_FLAG_TX_POWER;
6777
6778 return flags;
6779}
6780
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006781static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6782 void *data, u16 data_len)
6783{
6784 struct mgmt_rp_read_adv_features *rp;
6785 size_t rp_len;
6786 int err;
Arman Uguray24b4f382015-03-23 15:57:12 -07006787 bool instance;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006788 u32 supported_flags;
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006789
6790 BT_DBG("%s", hdev->name);
6791
Arman Uguray089fa8c2015-03-25 18:53:45 -07006792 if (!lmp_le_capable(hdev))
6793 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6794 MGMT_STATUS_REJECTED);
6795
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006796 hci_dev_lock(hdev);
6797
6798 rp_len = sizeof(*rp);
Arman Uguray24b4f382015-03-23 15:57:12 -07006799
6800 /* Currently only one instance is supported, so just add 1 to the
6801 * response length.
6802 */
6803 instance = hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE);
6804 if (instance)
6805 rp_len++;
6806
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006807 rp = kmalloc(rp_len, GFP_ATOMIC);
6808 if (!rp) {
6809 hci_dev_unlock(hdev);
6810 return -ENOMEM;
6811 }
6812
Arman Uguray089fa8c2015-03-25 18:53:45 -07006813 supported_flags = get_supported_adv_flags(hdev);
6814
6815 rp->supported_flags = cpu_to_le32(supported_flags);
Marcel Holtmanndc5d82a2015-03-19 17:22:25 -07006816 rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
6817 rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006818 rp->max_instances = 1;
6819
6820 /* Currently only one instance is supported, so simply return the
6821 * current instance number.
6822 */
6823 if (instance) {
6824 rp->num_instances = 1;
6825 rp->instance[0] = 1;
6826 } else {
6827 rp->num_instances = 0;
6828 }
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006829
6830 hci_dev_unlock(hdev);
6831
6832 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6833 MGMT_STATUS_SUCCESS, rp, rp_len);
6834
6835 kfree(rp);
6836
6837 return err;
6838}
6839
Arman Uguray4117ed72015-03-23 15:57:14 -07006840static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006841 u8 len, bool is_adv_data)
Arman Uguray24b4f382015-03-23 15:57:12 -07006842{
Arman Uguray4117ed72015-03-23 15:57:14 -07006843 u8 max_len = HCI_MAX_AD_LENGTH;
Arman Uguray24b4f382015-03-23 15:57:12 -07006844 int i, cur_len;
Arman Ugurayb44133f2015-03-25 18:53:41 -07006845 bool flags_managed = false;
Arman Uguray5507e352015-03-25 18:53:44 -07006846 bool tx_power_managed = false;
Arman Uguray67e0c0c2015-03-25 18:53:43 -07006847 u32 flags_params = MGMT_ADV_FLAG_DISCOV | MGMT_ADV_FLAG_LIMITED_DISCOV |
6848 MGMT_ADV_FLAG_MANAGED_FLAGS;
Arman Uguray24b4f382015-03-23 15:57:12 -07006849
Arman Uguray807ec772015-03-25 18:53:42 -07006850 if (is_adv_data && (adv_flags & flags_params)) {
Arman Ugurayb44133f2015-03-25 18:53:41 -07006851 flags_managed = true;
6852 max_len -= 3;
6853 }
Arman Uguray24b4f382015-03-23 15:57:12 -07006854
Arman Uguray5507e352015-03-25 18:53:44 -07006855 if (is_adv_data && (adv_flags & MGMT_ADV_FLAG_TX_POWER)) {
6856 tx_power_managed = true;
6857 max_len -= 3;
6858 }
6859
Arman Uguray4117ed72015-03-23 15:57:14 -07006860 if (len > max_len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006861 return false;
6862
Arman Uguray4117ed72015-03-23 15:57:14 -07006863 /* Make sure that the data is correctly formatted. */
6864 for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
6865 cur_len = data[i];
Arman Uguray24b4f382015-03-23 15:57:12 -07006866
Arman Ugurayb44133f2015-03-25 18:53:41 -07006867 if (flags_managed && data[i + 1] == EIR_FLAGS)
6868 return false;
6869
Arman Uguray5507e352015-03-25 18:53:44 -07006870 if (tx_power_managed && data[i + 1] == EIR_TX_POWER)
6871 return false;
6872
Arman Uguray24b4f382015-03-23 15:57:12 -07006873 /* If the current field length would exceed the total data
6874 * length, then it's invalid.
6875 */
Arman Uguray4117ed72015-03-23 15:57:14 -07006876 if (i + cur_len >= len)
Arman Uguray24b4f382015-03-23 15:57:12 -07006877 return false;
6878 }
6879
6880 return true;
6881}
6882
Arman Uguray24b4f382015-03-23 15:57:12 -07006883static void add_advertising_complete(struct hci_dev *hdev, u8 status,
6884 u16 opcode)
6885{
6886 struct mgmt_pending_cmd *cmd;
6887 struct mgmt_rp_add_advertising rp;
6888
6889 BT_DBG("status %d", status);
6890
6891 hci_dev_lock(hdev);
6892
6893 cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
6894
6895 if (status) {
6896 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
6897 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
6898 advertising_removed(cmd ? cmd->sk : NULL, hdev, 1);
6899 }
6900
6901 if (!cmd)
6902 goto unlock;
6903
6904 rp.instance = 0x01;
6905
6906 if (status)
6907 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
6908 mgmt_status(status));
6909 else
6910 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
6911 mgmt_status(status), &rp, sizeof(rp));
6912
6913 mgmt_pending_remove(cmd);
6914
6915unlock:
6916 hci_dev_unlock(hdev);
6917}
6918
Arman Uguray912098a2015-03-23 15:57:15 -07006919static void adv_timeout_expired(struct work_struct *work)
6920{
6921 struct hci_dev *hdev = container_of(work, struct hci_dev,
6922 adv_instance.timeout_exp.work);
6923
6924 hdev->adv_instance.timeout = 0;
6925
6926 hci_dev_lock(hdev);
6927 clear_adv_instance(hdev);
6928 hci_dev_unlock(hdev);
6929}
6930
Arman Uguray24b4f382015-03-23 15:57:12 -07006931static int add_advertising(struct sock *sk, struct hci_dev *hdev,
6932 void *data, u16 data_len)
6933{
6934 struct mgmt_cp_add_advertising *cp = data;
6935 struct mgmt_rp_add_advertising rp;
6936 u32 flags;
Arman Uguray089fa8c2015-03-25 18:53:45 -07006937 u32 supported_flags;
Arman Uguray24b4f382015-03-23 15:57:12 -07006938 u8 status;
Arman Uguray912098a2015-03-23 15:57:15 -07006939 u16 timeout;
Arman Uguray24b4f382015-03-23 15:57:12 -07006940 int err;
6941 struct mgmt_pending_cmd *cmd;
6942 struct hci_request req;
6943
6944 BT_DBG("%s", hdev->name);
6945
6946 status = mgmt_le_support(hdev);
6947 if (status)
6948 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6949 status);
6950
6951 flags = __le32_to_cpu(cp->flags);
Arman Uguray912098a2015-03-23 15:57:15 -07006952 timeout = __le16_to_cpu(cp->timeout);
Arman Uguray24b4f382015-03-23 15:57:12 -07006953
Arman Uguray089fa8c2015-03-25 18:53:45 -07006954 /* The current implementation only supports adding one instance and only
6955 * a subset of the specified flags.
6956 */
6957 supported_flags = get_supported_adv_flags(hdev);
6958 if (cp->instance != 0x01 || (flags & ~supported_flags))
Arman Uguray24b4f382015-03-23 15:57:12 -07006959 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6960 MGMT_STATUS_INVALID_PARAMS);
6961
6962 hci_dev_lock(hdev);
6963
Arman Uguray912098a2015-03-23 15:57:15 -07006964 if (timeout && !hdev_is_powered(hdev)) {
6965 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6966 MGMT_STATUS_REJECTED);
6967 goto unlock;
6968 }
6969
Arman Uguray24b4f382015-03-23 15:57:12 -07006970 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
Arman Ugurayda9293352015-03-23 15:57:13 -07006971 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
Arman Uguray24b4f382015-03-23 15:57:12 -07006972 pending_find(MGMT_OP_SET_LE, hdev)) {
6973 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6974 MGMT_STATUS_BUSY);
6975 goto unlock;
6976 }
6977
Arman Ugurayb44133f2015-03-25 18:53:41 -07006978 if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
Arman Uguray4117ed72015-03-23 15:57:14 -07006979 !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
Arman Ugurayb44133f2015-03-25 18:53:41 -07006980 cp->scan_rsp_len, false)) {
Arman Uguray24b4f382015-03-23 15:57:12 -07006981 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6982 MGMT_STATUS_INVALID_PARAMS);
6983 goto unlock;
6984 }
6985
Arman Uguray912098a2015-03-23 15:57:15 -07006986 INIT_DELAYED_WORK(&hdev->adv_instance.timeout_exp, adv_timeout_expired);
6987
Arman Uguray24b4f382015-03-23 15:57:12 -07006988 hdev->adv_instance.flags = flags;
6989 hdev->adv_instance.adv_data_len = cp->adv_data_len;
6990 hdev->adv_instance.scan_rsp_len = cp->scan_rsp_len;
6991
6992 if (cp->adv_data_len)
6993 memcpy(hdev->adv_instance.adv_data, cp->data, cp->adv_data_len);
6994
6995 if (cp->scan_rsp_len)
6996 memcpy(hdev->adv_instance.scan_rsp_data,
6997 cp->data + cp->adv_data_len, cp->scan_rsp_len);
6998
Arman Uguray912098a2015-03-23 15:57:15 -07006999 if (hdev->adv_instance.timeout)
7000 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
7001
7002 hdev->adv_instance.timeout = timeout;
7003
7004 if (timeout)
7005 queue_delayed_work(hdev->workqueue,
7006 &hdev->adv_instance.timeout_exp,
7007 msecs_to_jiffies(timeout * 1000));
7008
Arman Uguray24b4f382015-03-23 15:57:12 -07007009 if (!hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING_INSTANCE))
7010 advertising_added(sk, hdev, 1);
7011
7012 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7013 * we have no HCI communication to make. Simply return.
7014 */
7015 if (!hdev_is_powered(hdev) ||
7016 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7017 rp.instance = 0x01;
7018 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7019 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7020 goto unlock;
7021 }
7022
7023 /* We're good to go, update advertising data, parameters, and start
7024 * advertising.
7025 */
7026 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
7027 data_len);
7028 if (!cmd) {
7029 err = -ENOMEM;
7030 goto unlock;
7031 }
7032
7033 hci_req_init(&req, hdev);
7034
7035 update_adv_data(&req);
Arman Uguray4117ed72015-03-23 15:57:14 -07007036 update_scan_rsp_data(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007037 enable_advertising(&req);
7038
7039 err = hci_req_run(&req, add_advertising_complete);
7040 if (err < 0)
7041 mgmt_pending_remove(cmd);
7042
7043unlock:
7044 hci_dev_unlock(hdev);
7045
7046 return err;
7047}
7048
Arman Ugurayda9293352015-03-23 15:57:13 -07007049static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
7050 u16 opcode)
7051{
7052 struct mgmt_pending_cmd *cmd;
7053 struct mgmt_rp_remove_advertising rp;
7054
7055 BT_DBG("status %d", status);
7056
7057 hci_dev_lock(hdev);
7058
7059 /* A failure status here only means that we failed to disable
7060 * advertising. Otherwise, the advertising instance has been removed,
7061 * so report success.
7062 */
7063 cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
7064 if (!cmd)
7065 goto unlock;
7066
7067 rp.instance = 1;
7068
7069 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
7070 &rp, sizeof(rp));
7071 mgmt_pending_remove(cmd);
7072
7073unlock:
7074 hci_dev_unlock(hdev);
7075}
7076
7077static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
7078 void *data, u16 data_len)
7079{
7080 struct mgmt_cp_remove_advertising *cp = data;
7081 struct mgmt_rp_remove_advertising rp;
7082 int err;
7083 struct mgmt_pending_cmd *cmd;
7084 struct hci_request req;
7085
7086 BT_DBG("%s", hdev->name);
7087
7088 /* The current implementation only allows modifying instance no 1. A
7089 * value of 0 indicates that all instances should be cleared.
7090 */
7091 if (cp->instance > 1)
7092 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7093 MGMT_STATUS_INVALID_PARAMS);
7094
7095 hci_dev_lock(hdev);
7096
7097 if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
7098 pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
7099 pending_find(MGMT_OP_SET_LE, hdev)) {
7100 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7101 MGMT_STATUS_BUSY);
7102 goto unlock;
7103 }
7104
7105 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE)) {
7106 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
7107 MGMT_STATUS_INVALID_PARAMS);
7108 goto unlock;
7109 }
7110
Arman Uguray912098a2015-03-23 15:57:15 -07007111 if (hdev->adv_instance.timeout)
7112 cancel_delayed_work(&hdev->adv_instance.timeout_exp);
7113
Arman Ugurayda9293352015-03-23 15:57:13 -07007114 memset(&hdev->adv_instance, 0, sizeof(hdev->adv_instance));
7115
7116 advertising_removed(sk, hdev, 1);
7117
7118 hci_dev_clear_flag(hdev, HCI_ADVERTISING_INSTANCE);
7119
7120 /* If the HCI_ADVERTISING flag is set or the device isn't powered then
7121 * we have no HCI communication to make. Simply return.
7122 */
7123 if (!hdev_is_powered(hdev) ||
7124 hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
7125 rp.instance = 1;
7126 err = mgmt_cmd_complete(sk, hdev->id,
7127 MGMT_OP_REMOVE_ADVERTISING,
7128 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
7129 goto unlock;
7130 }
7131
7132 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
7133 data_len);
7134 if (!cmd) {
7135 err = -ENOMEM;
7136 goto unlock;
7137 }
7138
7139 hci_req_init(&req, hdev);
7140 disable_advertising(&req);
7141
7142 err = hci_req_run(&req, remove_advertising_complete);
7143 if (err < 0)
7144 mgmt_pending_remove(cmd);
7145
7146unlock:
7147 hci_dev_unlock(hdev);
7148
7149 return err;
7150}
7151
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007152static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007153 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007154 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007155 HCI_MGMT_NO_HDEV |
7156 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007157 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007158 HCI_MGMT_NO_HDEV |
7159 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007160 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007161 HCI_MGMT_NO_HDEV |
7162 HCI_MGMT_UNTRUSTED },
7163 { read_controller_info, MGMT_READ_INFO_SIZE,
7164 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007165 { set_powered, MGMT_SETTING_SIZE },
7166 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
7167 { set_connectable, MGMT_SETTING_SIZE },
7168 { set_fast_connectable, MGMT_SETTING_SIZE },
7169 { set_bondable, MGMT_SETTING_SIZE },
7170 { set_link_security, MGMT_SETTING_SIZE },
7171 { set_ssp, MGMT_SETTING_SIZE },
7172 { set_hs, MGMT_SETTING_SIZE },
7173 { set_le, MGMT_SETTING_SIZE },
7174 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
7175 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
7176 { add_uuid, MGMT_ADD_UUID_SIZE },
7177 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007178 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
7179 HCI_MGMT_VAR_LEN },
7180 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
7181 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007182 { disconnect, MGMT_DISCONNECT_SIZE },
7183 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
7184 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
7185 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
7186 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
7187 { pair_device, MGMT_PAIR_DEVICE_SIZE },
7188 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
7189 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
7190 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
7191 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
7192 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
7193 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007194 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
7195 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
7196 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007197 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
7198 { start_discovery, MGMT_START_DISCOVERY_SIZE },
7199 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
7200 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
7201 { block_device, MGMT_BLOCK_DEVICE_SIZE },
7202 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
7203 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
7204 { set_advertising, MGMT_SETTING_SIZE },
7205 { set_bredr, MGMT_SETTING_SIZE },
7206 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
7207 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
7208 { set_secure_conn, MGMT_SETTING_SIZE },
7209 { set_debug_keys, MGMT_SETTING_SIZE },
7210 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007211 { load_irks, MGMT_LOAD_IRKS_SIZE,
7212 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07007213 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
7214 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
7215 { add_device, MGMT_ADD_DEVICE_SIZE },
7216 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007217 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
7218 HCI_MGMT_VAR_LEN },
7219 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007220 HCI_MGMT_NO_HDEV |
7221 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007222 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007223 HCI_MGMT_UNCONFIGURED |
7224 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02007225 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
7226 HCI_MGMT_UNCONFIGURED },
7227 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
7228 HCI_MGMT_UNCONFIGURED },
7229 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
7230 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07007231 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07007232 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07007233 HCI_MGMT_NO_HDEV |
7234 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07007235 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Arman Uguray24b4f382015-03-23 15:57:12 -07007236 { add_advertising, MGMT_ADD_ADVERTISING_SIZE,
7237 HCI_MGMT_VAR_LEN },
Arman Ugurayda9293352015-03-23 15:57:13 -07007238 { remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02007239};
7240
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007241void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007242{
Marcel Holtmannced85542015-03-14 19:27:56 -07007243 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03007244
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007245 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7246 return;
7247
Marcel Holtmannf9207332015-03-14 19:27:55 -07007248 switch (hdev->dev_type) {
7249 case HCI_BREDR:
7250 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7251 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
7252 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007253 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007254 } else {
7255 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
7256 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007257 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007258 }
7259 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007260 case HCI_AMP:
7261 ev.type = 0x02;
7262 break;
7263 default:
7264 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007265 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007266
7267 ev.bus = hdev->bus;
7268
7269 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
7270 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007271}
7272
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07007273void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02007274{
Marcel Holtmannced85542015-03-14 19:27:56 -07007275 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02007276 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007277
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02007278 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
7279 return;
7280
Marcel Holtmannf9207332015-03-14 19:27:55 -07007281 switch (hdev->dev_type) {
7282 case HCI_BREDR:
7283 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02007284
Marcel Holtmannf9207332015-03-14 19:27:55 -07007285 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
7286 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
7287 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007288 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007289 } else {
7290 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
7291 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07007292 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007293 }
7294 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07007295 case HCI_AMP:
7296 ev.type = 0x02;
7297 break;
7298 default:
7299 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07007300 }
Marcel Holtmannced85542015-03-14 19:27:56 -07007301
7302 ev.bus = hdev->bus;
7303
7304 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
7305 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007306}
7307
Andre Guedes6046dc32014-02-26 20:21:51 -03007308/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02007309static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03007310{
Johan Hedberg2cf22212014-12-19 22:26:00 +02007311 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03007312 struct hci_conn_params *p;
7313
7314 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03007315 /* Needed for AUTO_OFF case where might not "really"
7316 * have been powered off.
7317 */
7318 list_del_init(&p->action);
7319
7320 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02007321 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03007322 case HCI_AUTO_CONN_ALWAYS:
7323 list_add(&p->action, &hdev->pend_le_conns);
7324 break;
7325 case HCI_AUTO_CONN_REPORT:
7326 list_add(&p->action, &hdev->pend_le_reports);
7327 break;
7328 default:
7329 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007330 }
Andre Guedes6046dc32014-02-26 20:21:51 -03007331 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02007332
Johan Hedberg2cf22212014-12-19 22:26:00 +02007333 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03007334}
7335
Marcel Holtmann1904a852015-01-11 13:50:44 -08007336static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05007337{
7338 struct cmd_lookup match = { NULL, hdev };
7339
7340 BT_DBG("status 0x%02x", status);
7341
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08007342 if (!status) {
7343 /* Register the available SMP channels (BR/EDR and LE) only
7344 * when successfully powering on the controller. This late
7345 * registration is required so that LE SMP can clearly
7346 * decide if the public address or static address is used.
7347 */
7348 smp_register(hdev);
7349 }
7350
Johan Hedberg229ab392013-03-15 17:06:53 -05007351 hci_dev_lock(hdev);
7352
7353 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
7354
7355 new_settings(hdev, match.sk);
7356
7357 hci_dev_unlock(hdev);
7358
7359 if (match.sk)
7360 sock_put(match.sk);
7361}
7362
Johan Hedberg70da6242013-03-15 17:06:51 -05007363static int powered_update_hci(struct hci_dev *hdev)
7364{
Johan Hedberg890ea892013-03-15 17:06:52 -05007365 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05007366 u8 link_sec;
7367
Johan Hedberg890ea892013-03-15 17:06:52 -05007368 hci_req_init(&req, hdev);
7369
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007370 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05007371 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007372 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05007373
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007374 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05007375
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08007376 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
7377 u8 support = 0x01;
7378
7379 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
7380 sizeof(support), &support);
7381 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02007382 }
7383
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007384 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03007385 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05007386 struct hci_cp_write_le_host_supported cp;
7387
Marcel Holtmann32226e42014-07-24 20:04:16 +02007388 cp.le = 0x01;
7389 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05007390
7391 /* Check first if we already have the right
7392 * host state (host features set)
7393 */
7394 if (cp.le != lmp_host_le_capable(hdev) ||
7395 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007396 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
7397 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05007398 }
7399
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07007400 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007401 /* Make sure the controller has a good default for
7402 * advertising data. This also applies to the case
7403 * where BR/EDR was toggled during the AUTO_OFF phase.
7404 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007405 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07007406 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07007407 update_scan_rsp_data(&req);
7408 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07007409
Arman Uguray24b4f382015-03-23 15:57:12 -07007410 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7411 hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07007412 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02007413
7414 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03007415 }
7416
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007417 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05007418 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05007419 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
7420 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05007421
7422 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007423 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02007424 write_fast_connectable(&req, true);
7425 else
7426 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02007427 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007428 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05007429 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05007430 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05007431 }
7432
Johan Hedberg229ab392013-03-15 17:06:53 -05007433 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05007434}
7435
Johan Hedberg744cf192011-11-08 20:40:14 +02007436int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02007437{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02007438 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02007439 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007440 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007441
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007442 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007443 return 0;
7444
Johan Hedberg5e5282b2012-02-21 16:01:30 +02007445 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05007446 if (powered_update_hci(hdev) == 0)
7447 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02007448
Johan Hedberg229ab392013-03-15 17:06:53 -05007449 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
7450 &match);
7451 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02007452 }
7453
Johan Hedberg229ab392013-03-15 17:06:53 -05007454 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02007455
7456 /* If the power off is because of hdev unregistration let
7457 * use the appropriate INVALID_INDEX status. Otherwise use
7458 * NOT_POWERED. We cover both scenarios here since later in
7459 * mgmt_index_removed() any hci_conn callbacks will have already
7460 * been triggered, potentially causing misleading DISCONNECTED
7461 * status responses.
7462 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007463 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02007464 status = MGMT_STATUS_INVALID_INDEX;
7465 else
7466 status = MGMT_STATUS_NOT_POWERED;
7467
7468 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05007469
7470 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007471 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7472 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05007473
7474new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02007475 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02007476
7477 if (match.sk)
7478 sock_put(match.sk);
7479
Johan Hedberg7bb895d2012-02-17 01:20:00 +02007480 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02007481}
Johan Hedberg73f22f62010-12-29 16:00:25 +02007482
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007483void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03007484{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007485 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007486 u8 status;
7487
Johan Hedberg333ae952015-03-17 13:48:47 +02007488 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007489 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07007490 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03007491
7492 if (err == -ERFKILL)
7493 status = MGMT_STATUS_RFKILLED;
7494 else
7495 status = MGMT_STATUS_FAILED;
7496
Johan Hedberga69e8372015-03-06 21:08:53 +02007497 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007498
7499 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03007500}
7501
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007502void mgmt_discoverable_timeout(struct hci_dev *hdev)
7503{
7504 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007505
7506 hci_dev_lock(hdev);
7507
7508 /* When discoverable timeout triggers, then just make sure
7509 * the limited discoverable flag is cleared. Even in the case
7510 * of a timeout triggered from general discoverable, it is
7511 * safe to unconditionally clear the flag.
7512 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007513 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
7514 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007515
7516 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007517 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03007518 u8 scan = SCAN_PAGE;
7519 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
7520 sizeof(scan), &scan);
7521 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007522 update_class(&req);
Arman Uguray24b4f382015-03-23 15:57:12 -07007523
7524 /* Advertising instances don't use the global discoverable setting, so
7525 * only update AD if advertising was enabled using Set Advertising.
7526 */
7527 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7528 update_adv_data(&req);
7529
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007530 hci_req_run(&req, NULL);
7531
7532 hdev->discov_timeout = 0;
7533
Johan Hedberg9a43e252013-10-20 19:00:07 +03007534 new_settings(hdev, NULL);
7535
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07007536 hci_dev_unlock(hdev);
7537}
7538
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007539void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
7540 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007541{
Johan Hedberg86742e12011-11-07 23:13:38 +02007542 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007543
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007544 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007545
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007546 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02007547 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007548 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007549 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03007550 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03007551 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007552
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07007553 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02007554}
Johan Hedbergf7520542011-01-20 12:34:39 +02007555
Johan Hedbergd7b25452014-05-23 13:19:53 +03007556static u8 mgmt_ltk_type(struct smp_ltk *ltk)
7557{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03007558 switch (ltk->type) {
7559 case SMP_LTK:
7560 case SMP_LTK_SLAVE:
7561 if (ltk->authenticated)
7562 return MGMT_LTK_AUTHENTICATED;
7563 return MGMT_LTK_UNAUTHENTICATED;
7564 case SMP_LTK_P256:
7565 if (ltk->authenticated)
7566 return MGMT_LTK_P256_AUTH;
7567 return MGMT_LTK_P256_UNAUTH;
7568 case SMP_LTK_P256_DEBUG:
7569 return MGMT_LTK_P256_DEBUG;
7570 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03007571
7572 return MGMT_LTK_UNAUTHENTICATED;
7573}
7574
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007575void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007576{
7577 struct mgmt_ev_new_long_term_key ev;
7578
7579 memset(&ev, 0, sizeof(ev));
7580
Marcel Holtmann5192d302014-02-19 17:11:58 -08007581 /* Devices using resolvable or non-resolvable random addresses
7582 * without providing an indentity resolving key don't require
7583 * to store long term keys. Their addresses will change the
7584 * next time around.
7585 *
7586 * Only when a remote device provides an identity address
7587 * make sure the long term key is stored. If the remote
7588 * identity is known, the long term keys are internally
7589 * mapped to the identity address. So allow static random
7590 * and public addresses here.
7591 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007592 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7593 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7594 ev.store_hint = 0x00;
7595 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007596 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007597
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007598 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007599 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007600 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007601 ev.key.enc_size = key->enc_size;
7602 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007603 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007604
Johan Hedberg2ceba532014-06-16 19:25:16 +03007605 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007606 ev.key.master = 1;
7607
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007608 memcpy(ev.key.val, key->val, sizeof(key->val));
7609
Marcel Holtmann083368f2013-10-15 14:26:29 -07007610 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007611}
7612
Johan Hedberg95fbac82014-02-19 15:18:31 +02007613void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7614{
7615 struct mgmt_ev_new_irk ev;
7616
7617 memset(&ev, 0, sizeof(ev));
7618
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007619 /* For identity resolving keys from devices that are already
7620 * using a public address or static random address, do not
7621 * ask for storing this key. The identity resolving key really
7622 * is only mandatory for devices using resovlable random
7623 * addresses.
7624 *
7625 * Storing all identity resolving keys has the downside that
7626 * they will be also loaded on next boot of they system. More
7627 * identity resolving keys, means more time during scanning is
7628 * needed to actually resolve these addresses.
7629 */
7630 if (bacmp(&irk->rpa, BDADDR_ANY))
7631 ev.store_hint = 0x01;
7632 else
7633 ev.store_hint = 0x00;
7634
Johan Hedberg95fbac82014-02-19 15:18:31 +02007635 bacpy(&ev.rpa, &irk->rpa);
7636 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7637 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7638 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7639
7640 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7641}
7642
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007643void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7644 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007645{
7646 struct mgmt_ev_new_csrk ev;
7647
7648 memset(&ev, 0, sizeof(ev));
7649
7650 /* Devices using resolvable or non-resolvable random addresses
7651 * without providing an indentity resolving key don't require
7652 * to store signature resolving keys. Their addresses will change
7653 * the next time around.
7654 *
7655 * Only when a remote device provides an identity address
7656 * make sure the signature resolving key is stored. So allow
7657 * static random and public addresses here.
7658 */
7659 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7660 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7661 ev.store_hint = 0x00;
7662 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007663 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007664
7665 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7666 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007667 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007668 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7669
7670 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7671}
7672
Andre Guedesffb5a8272014-07-01 18:10:11 -03007673void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007674 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7675 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007676{
7677 struct mgmt_ev_new_conn_param ev;
7678
Johan Hedbergc103aea2014-07-02 17:37:34 +03007679 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7680 return;
7681
Andre Guedesffb5a8272014-07-01 18:10:11 -03007682 memset(&ev, 0, sizeof(ev));
7683 bacpy(&ev.addr.bdaddr, bdaddr);
7684 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007685 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007686 ev.min_interval = cpu_to_le16(min_interval);
7687 ev.max_interval = cpu_to_le16(max_interval);
7688 ev.latency = cpu_to_le16(latency);
7689 ev.timeout = cpu_to_le16(timeout);
7690
7691 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7692}
7693
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007694void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7695 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007696{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007697 char buf[512];
7698 struct mgmt_ev_device_connected *ev = (void *) buf;
7699 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007700
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007701 bacpy(&ev->addr.bdaddr, &conn->dst);
7702 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007703
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007704 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007705
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007706 /* We must ensure that the EIR Data fields are ordered and
7707 * unique. Keep it simple for now and avoid the problem by not
7708 * adding any BR/EDR data to the LE adv.
7709 */
7710 if (conn->le_adv_data_len > 0) {
7711 memcpy(&ev->eir[eir_len],
7712 conn->le_adv_data, conn->le_adv_data_len);
7713 eir_len = conn->le_adv_data_len;
7714 } else {
7715 if (name_len > 0)
7716 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7717 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007718
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007719 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007720 eir_len = eir_append_data(ev->eir, eir_len,
7721 EIR_CLASS_OF_DEV,
7722 conn->dev_class, 3);
7723 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007724
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007725 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007726
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007727 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7728 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007729}
7730
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007731static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007732{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007733 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007734
Johan Hedbergf5818c22014-12-05 13:36:02 +02007735 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007736
7737 *sk = cmd->sk;
7738 sock_hold(*sk);
7739
Johan Hedberga664b5b2011-02-19 12:06:02 -03007740 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007741}
7742
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007743static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007744{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007745 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007746 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007747
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007748 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7749
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007750 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007751 mgmt_pending_remove(cmd);
7752}
7753
Johan Hedberg84c61d92014-08-01 11:13:30 +03007754bool mgmt_powering_down(struct hci_dev *hdev)
7755{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007756 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007757 struct mgmt_mode *cp;
7758
Johan Hedberg333ae952015-03-17 13:48:47 +02007759 cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
Johan Hedberg84c61d92014-08-01 11:13:30 +03007760 if (!cmd)
7761 return false;
7762
7763 cp = cmd->param;
7764 if (!cp->val)
7765 return true;
7766
7767 return false;
7768}
7769
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007770void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007771 u8 link_type, u8 addr_type, u8 reason,
7772 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007773{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007774 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007775 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007776
Johan Hedberg84c61d92014-08-01 11:13:30 +03007777 /* The connection is still in hci_conn_hash so test for 1
7778 * instead of 0 to know if this is the last one.
7779 */
7780 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7781 cancel_delayed_work(&hdev->power_off);
7782 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007783 }
7784
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007785 if (!mgmt_connected)
7786 return;
7787
Andre Guedes57eb7762013-10-30 19:01:41 -03007788 if (link_type != ACL_LINK && link_type != LE_LINK)
7789 return;
7790
Johan Hedberg744cf192011-11-08 20:40:14 +02007791 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007792
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007793 bacpy(&ev.addr.bdaddr, bdaddr);
7794 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7795 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007796
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007797 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007798
7799 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007800 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007801
Johan Hedberg124f6e32012-02-09 13:50:12 +02007802 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007803 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007804}
7805
Marcel Holtmann78929242013-10-06 23:55:47 -07007806void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7807 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007808{
Andre Guedes3655bba2013-10-30 19:01:40 -03007809 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7810 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007811 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007812
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007813 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7814 hdev);
7815
Johan Hedberg333ae952015-03-17 13:48:47 +02007816 cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007817 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007818 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007819
Andre Guedes3655bba2013-10-30 19:01:40 -03007820 cp = cmd->param;
7821
7822 if (bacmp(bdaddr, &cp->addr.bdaddr))
7823 return;
7824
7825 if (cp->addr.type != bdaddr_type)
7826 return;
7827
Johan Hedbergf5818c22014-12-05 13:36:02 +02007828 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007829 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007830}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007831
Marcel Holtmann445608d2013-10-06 23:55:48 -07007832void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7833 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007834{
7835 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007836
Johan Hedberg84c61d92014-08-01 11:13:30 +03007837 /* The connection is still in hci_conn_hash so test for 1
7838 * instead of 0 to know if this is the last one.
7839 */
7840 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7841 cancel_delayed_work(&hdev->power_off);
7842 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007843 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007844
Johan Hedberg4c659c32011-11-07 23:13:39 +02007845 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007846 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007847 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007848
Marcel Holtmann445608d2013-10-06 23:55:48 -07007849 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007850}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007851
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007852void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007853{
7854 struct mgmt_ev_pin_code_request ev;
7855
Johan Hedbergd8457692012-02-17 14:24:57 +02007856 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007857 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007858 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007859
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007860 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007861}
7862
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007863void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7864 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007865{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007866 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007867
Johan Hedberg333ae952015-03-17 13:48:47 +02007868 cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007869 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007870 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007871
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007872 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007873 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007874}
7875
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007876void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7877 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007878{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007879 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007880
Johan Hedberg333ae952015-03-17 13:48:47 +02007881 cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007882 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007883 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007884
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007885 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007886 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007887}
Johan Hedberga5c29682011-02-19 12:05:57 -03007888
Johan Hedberg744cf192011-11-08 20:40:14 +02007889int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007890 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007891 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007892{
7893 struct mgmt_ev_user_confirm_request ev;
7894
Johan Hedberg744cf192011-11-08 20:40:14 +02007895 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007896
Johan Hedberg272d90d2012-02-09 15:26:12 +02007897 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007898 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007899 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007900 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007901
Johan Hedberg744cf192011-11-08 20:40:14 +02007902 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007903 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007904}
7905
Johan Hedberg272d90d2012-02-09 15:26:12 +02007906int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007907 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007908{
7909 struct mgmt_ev_user_passkey_request ev;
7910
7911 BT_DBG("%s", hdev->name);
7912
Johan Hedberg272d90d2012-02-09 15:26:12 +02007913 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007914 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007915
7916 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007917 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007918}
7919
Brian Gix0df4c182011-11-16 13:53:13 -08007920static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007921 u8 link_type, u8 addr_type, u8 status,
7922 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007923{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007924 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007925
Johan Hedberg333ae952015-03-17 13:48:47 +02007926 cmd = pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007927 if (!cmd)
7928 return -ENOENT;
7929
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007930 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007931 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007932
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007933 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007934}
7935
Johan Hedberg744cf192011-11-08 20:40:14 +02007936int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007937 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007938{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007939 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007940 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007941}
7942
Johan Hedberg272d90d2012-02-09 15:26:12 +02007943int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007944 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007945{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007946 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007947 status,
7948 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007949}
Johan Hedberg2a611692011-02-19 12:06:00 -03007950
Brian Gix604086b2011-11-23 08:28:33 -08007951int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007952 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007953{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007954 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007955 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007956}
7957
Johan Hedberg272d90d2012-02-09 15:26:12 +02007958int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007959 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007960{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007961 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007962 status,
7963 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007964}
7965
Johan Hedberg92a25252012-09-06 18:39:26 +03007966int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7967 u8 link_type, u8 addr_type, u32 passkey,
7968 u8 entered)
7969{
7970 struct mgmt_ev_passkey_notify ev;
7971
7972 BT_DBG("%s", hdev->name);
7973
7974 bacpy(&ev.addr.bdaddr, bdaddr);
7975 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7976 ev.passkey = __cpu_to_le32(passkey);
7977 ev.entered = entered;
7978
7979 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7980}
7981
Johan Hedberge1e930f2014-09-08 17:09:49 -07007982void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007983{
7984 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007985 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007986 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007987
Johan Hedberge1e930f2014-09-08 17:09:49 -07007988 bacpy(&ev.addr.bdaddr, &conn->dst);
7989 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7990 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007991
Johan Hedberge1e930f2014-09-08 17:09:49 -07007992 cmd = find_pairing(conn);
7993
7994 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7995 cmd ? cmd->sk : NULL);
7996
Johan Hedberga511b352014-12-11 21:45:45 +02007997 if (cmd) {
7998 cmd->cmd_complete(cmd, status);
7999 mgmt_pending_remove(cmd);
8000 }
Johan Hedberg2a611692011-02-19 12:06:00 -03008001}
Johan Hedbergb312b1612011-03-16 14:29:37 +02008002
Marcel Holtmann464996a2013-10-15 14:26:24 -07008003void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008004{
8005 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07008006 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008007
8008 if (status) {
8009 u8 mgmt_err = mgmt_status(status);
8010 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008011 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07008012 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008013 }
8014
Marcel Holtmann464996a2013-10-15 14:26:24 -07008015 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07008016 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07008017 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008018 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02008019
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008020 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008021 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008022
Johan Hedberg47990ea2012-02-22 11:58:37 +02008023 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07008024 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008025
8026 if (match.sk)
8027 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02008028}
8029
Johan Hedberg890ea892013-03-15 17:06:52 -05008030static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02008031{
Johan Hedberg890ea892013-03-15 17:06:52 -05008032 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008033 struct hci_cp_write_eir cp;
8034
Johan Hedberg976eb202012-10-24 21:12:01 +03008035 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05008036 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02008037
Johan Hedbergc80da272012-02-22 15:38:48 +02008038 memset(hdev->eir, 0, sizeof(hdev->eir));
8039
Johan Hedbergcacaf522012-02-21 00:52:42 +02008040 memset(&cp, 0, sizeof(cp));
8041
Johan Hedberg890ea892013-03-15 17:06:52 -05008042 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02008043}
8044
Marcel Holtmann3e248562013-10-15 14:26:25 -07008045void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008046{
8047 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05008048 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008049 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008050
8051 if (status) {
8052 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008053
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008054 if (enable && hci_dev_test_and_clear_flag(hdev,
8055 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008056 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008057 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008058 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008059
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008060 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
8061 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07008062 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008063 }
8064
8065 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07008066 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008067 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008068 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008069 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07008070 changed = hci_dev_test_and_clear_flag(hdev,
8071 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07008072 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07008073 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008074 }
8075
8076 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
8077
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02008078 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07008079 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008080
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02008081 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008082 sock_put(match.sk);
8083
Johan Hedberg890ea892013-03-15 17:06:52 -05008084 hci_req_init(&req, hdev);
8085
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008086 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
8087 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03008088 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
8089 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05008090 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008091 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05008092 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03008093 }
Johan Hedberg890ea892013-03-15 17:06:52 -05008094
8095 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02008096}
8097
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008098static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02008099{
8100 struct cmd_lookup *match = data;
8101
Johan Hedberg90e70452012-02-23 23:09:40 +02008102 if (match->sk == NULL) {
8103 match->sk = cmd->sk;
8104 sock_hold(match->sk);
8105 }
Johan Hedberg90e70452012-02-23 23:09:40 +02008106}
8107
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07008108void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
8109 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008110{
Johan Hedberg90e70452012-02-23 23:09:40 +02008111 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008112
Johan Hedberg92da6092013-03-15 17:06:55 -05008113 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
8114 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
8115 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02008116
8117 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008118 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
8119 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02008120
8121 if (match.sk)
8122 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01008123}
8124
Marcel Holtmann7667da32013-10-15 14:26:27 -07008125void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02008126{
Johan Hedbergb312b1612011-03-16 14:29:37 +02008127 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02008128 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008129
Johan Hedberg13928972013-03-15 17:07:00 -05008130 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07008131 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008132
8133 memset(&ev, 0, sizeof(ev));
8134 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02008135 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008136
Johan Hedberg333ae952015-03-17 13:48:47 +02008137 cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05008138 if (!cmd) {
8139 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02008140
Johan Hedberg13928972013-03-15 17:07:00 -05008141 /* If this is a HCI command related to powering on the
8142 * HCI dev don't send any mgmt signals.
8143 */
Johan Hedberg333ae952015-03-17 13:48:47 +02008144 if (pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07008145 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02008146 }
8147
Marcel Holtmannf6b77122015-03-14 19:28:05 -07008148 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
8149 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02008150}
Szymon Jancc35938b2011-03-22 13:12:21 +01008151
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008152static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
8153{
8154 int i;
8155
8156 for (i = 0; i < uuid_count; i++) {
8157 if (!memcmp(uuid, uuids[i], 16))
8158 return true;
8159 }
8160
8161 return false;
8162}
8163
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008164static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
8165{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008166 u16 parsed = 0;
8167
8168 while (parsed < eir_len) {
8169 u8 field_len = eir[0];
8170 u8 uuid[16];
8171 int i;
8172
8173 if (field_len == 0)
8174 break;
8175
8176 if (eir_len - parsed < field_len + 1)
8177 break;
8178
8179 switch (eir[1]) {
8180 case EIR_UUID16_ALL:
8181 case EIR_UUID16_SOME:
8182 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008183 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008184 uuid[13] = eir[i + 3];
8185 uuid[12] = eir[i + 2];
8186 if (has_uuid(uuid, uuid_count, uuids))
8187 return true;
8188 }
8189 break;
8190 case EIR_UUID32_ALL:
8191 case EIR_UUID32_SOME:
8192 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02008193 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01008194 uuid[15] = eir[i + 5];
8195 uuid[14] = eir[i + 4];
8196 uuid[13] = eir[i + 3];
8197 uuid[12] = eir[i + 2];
8198 if (has_uuid(uuid, uuid_count, uuids))
8199 return true;
8200 }
8201 break;
8202 case EIR_UUID128_ALL:
8203 case EIR_UUID128_SOME:
8204 for (i = 0; i + 17 <= field_len; i += 16) {
8205 memcpy(uuid, eir + i + 2, 16);
8206 if (has_uuid(uuid, uuid_count, uuids))
8207 return true;
8208 }
8209 break;
8210 }
8211
8212 parsed += field_len + 1;
8213 eir += field_len + 1;
8214 }
8215
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008216 return false;
8217}
8218
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008219static void restart_le_scan(struct hci_dev *hdev)
8220{
8221 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07008222 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008223 return;
8224
8225 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
8226 hdev->discovery.scan_start +
8227 hdev->discovery.scan_duration))
8228 return;
8229
8230 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
8231 DISCOV_LE_RESTART_DELAY);
8232}
8233
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008234static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
8235 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
8236{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008237 /* If a RSSI threshold has been specified, and
8238 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
8239 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
8240 * is set, let it through for further processing, as we might need to
8241 * restart the scan.
8242 *
8243 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
8244 * the results are also dropped.
8245 */
8246 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8247 (rssi == HCI_RSSI_INVALID ||
8248 (rssi < hdev->discovery.rssi &&
8249 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
8250 return false;
8251
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008252 if (hdev->discovery.uuid_count != 0) {
8253 /* If a list of UUIDs is provided in filter, results with no
8254 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008255 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008256 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
8257 hdev->discovery.uuids) &&
8258 !eir_has_uuids(scan_rsp, scan_rsp_len,
8259 hdev->discovery.uuid_count,
8260 hdev->discovery.uuids))
8261 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008262 }
8263
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008264 /* If duplicate filtering does not report RSSI changes, then restart
8265 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008266 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08008267 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
8268 restart_le_scan(hdev);
8269
8270 /* Validate RSSI value against the RSSI threshold once more. */
8271 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
8272 rssi < hdev->discovery.rssi)
8273 return false;
8274 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008275
8276 return true;
8277}
8278
Marcel Holtmann901801b2013-10-06 23:55:51 -07008279void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02008280 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
8281 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03008282{
Johan Hedberge319d2e2012-01-15 19:51:59 +02008283 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008284 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02008285 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03008286
Johan Hedberg75ce2082014-07-02 22:42:01 +03008287 /* Don't send events for a non-kernel initiated discovery. With
8288 * LE one exception is if we have pend_le_reports > 0 in which
8289 * case we're doing passive scanning and want these events.
8290 */
8291 if (!hci_discovery_active(hdev)) {
8292 if (link_type == ACL_LINK)
8293 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03008294 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03008295 return;
8296 }
Andre Guedes12602d02013-04-30 15:29:40 -03008297
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08008298 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008299 /* We are using service discovery */
8300 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
8301 scan_rsp_len))
8302 return;
8303 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01008304
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008305 /* Make sure that the buffer is big enough. The 5 extra bytes
8306 * are for the potential CoD field.
8307 */
8308 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07008309 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03008310
Johan Hedberg1dc06092012-01-15 21:01:23 +02008311 memset(buf, 0, sizeof(buf));
8312
Marcel Holtmannda25cf62014-12-05 13:03:35 +01008313 /* In case of device discovery with BR/EDR devices (pre 1.2), the
8314 * RSSI value was reported as 0 when not available. This behavior
8315 * is kept when using device discovery. This is required for full
8316 * backwards compatibility with the API.
8317 *
8318 * However when using service discovery, the value 127 will be
8319 * returned when the RSSI is not available.
8320 */
Szymon Janc91200e92015-01-22 16:57:05 +01008321 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
8322 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01008323 rssi = 0;
8324
Johan Hedberg841c5642014-07-07 12:45:54 +03008325 bacpy(&ev->addr.bdaddr, bdaddr);
8326 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02008327 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02008328 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03008329
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008330 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008331 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02008332 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03008333
Johan Hedberg1dc06092012-01-15 21:01:23 +02008334 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
8335 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008336 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02008337
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08008338 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01008339 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008340 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08008341
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02008342 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
8343 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03008344
Marcel Holtmann901801b2013-10-06 23:55:51 -07008345 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03008346}
Johan Hedberga88a9652011-03-30 13:18:12 +03008347
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008348void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
8349 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03008350{
Johan Hedbergb644ba32012-01-17 21:48:47 +02008351 struct mgmt_ev_device_found *ev;
8352 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
8353 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03008354
Johan Hedbergb644ba32012-01-17 21:48:47 +02008355 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03008356
Johan Hedbergb644ba32012-01-17 21:48:47 +02008357 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03008358
Johan Hedbergb644ba32012-01-17 21:48:47 +02008359 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03008360 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008361 ev->rssi = rssi;
8362
8363 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03008364 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008365
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02008366 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02008367
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07008368 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03008369}
Johan Hedberg314b2382011-04-27 10:29:57 -04008370
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008371void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04008372{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008373 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02008374
Andre Guedes343fb142011-11-22 17:14:19 -03008375 BT_DBG("%s discovering %u", hdev->name, discovering);
8376
Johan Hedbergf963e8e2012-02-20 23:30:44 +02008377 memset(&ev, 0, sizeof(ev));
8378 ev.type = hdev->discovery.type;
8379 ev.discovering = discovering;
8380
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07008381 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04008382}
Antti Julku5e762442011-08-25 16:48:02 +03008383
Marcel Holtmann1904a852015-01-11 13:50:44 -08008384static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07008385{
8386 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008387}
8388
8389void mgmt_reenable_advertising(struct hci_dev *hdev)
8390{
8391 struct hci_request req;
8392
Arman Uguray24b4f382015-03-23 15:57:12 -07008393 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
8394 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))
Marcel Holtmann5976e602013-10-06 04:08:14 -07008395 return;
8396
8397 hci_req_init(&req, hdev);
8398 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03008399 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07008400}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008401
8402static struct hci_mgmt_chan chan = {
8403 .channel = HCI_CHANNEL_CONTROL,
8404 .handler_count = ARRAY_SIZE(mgmt_handlers),
8405 .handlers = mgmt_handlers,
Johan Hedberg88b94ce2015-03-17 13:48:49 +02008406 .hdev_init = mgmt_init_hdev,
Johan Hedberg6d785aa32015-03-06 21:08:51 +02008407};
8408
8409int mgmt_init(void)
8410{
8411 return hci_mgmt_chan_register(&chan);
8412}
8413
8414void mgmt_exit(void)
8415{
8416 hci_mgmt_chan_unregister(&chan);
8417}