blob: 0761f2e0fefae6c3521b76b00e1f349c2050da59 [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 Hedberg03811012010-12-08 00:21:06 +020038
Johan Hedberg2da9c552012-02-17 14:39:28 +020039#define MGMT_VERSION 1
Marcel Holtmannbeb1c212015-03-10 14:04:52 -070040#define MGMT_REVISION 9
Johan Hedberg02d98122010-12-13 21:07:04 +020041
Johan Hedberge70bb2e2012-02-13 16:59:33 +020042static const u16 mgmt_commands[] = {
43 MGMT_OP_READ_INDEX_LIST,
44 MGMT_OP_READ_INFO,
45 MGMT_OP_SET_POWERED,
46 MGMT_OP_SET_DISCOVERABLE,
47 MGMT_OP_SET_CONNECTABLE,
48 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030049 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020050 MGMT_OP_SET_LINK_SECURITY,
51 MGMT_OP_SET_SSP,
52 MGMT_OP_SET_HS,
53 MGMT_OP_SET_LE,
54 MGMT_OP_SET_DEV_CLASS,
55 MGMT_OP_SET_LOCAL_NAME,
56 MGMT_OP_ADD_UUID,
57 MGMT_OP_REMOVE_UUID,
58 MGMT_OP_LOAD_LINK_KEYS,
59 MGMT_OP_LOAD_LONG_TERM_KEYS,
60 MGMT_OP_DISCONNECT,
61 MGMT_OP_GET_CONNECTIONS,
62 MGMT_OP_PIN_CODE_REPLY,
63 MGMT_OP_PIN_CODE_NEG_REPLY,
64 MGMT_OP_SET_IO_CAPABILITY,
65 MGMT_OP_PAIR_DEVICE,
66 MGMT_OP_CANCEL_PAIR_DEVICE,
67 MGMT_OP_UNPAIR_DEVICE,
68 MGMT_OP_USER_CONFIRM_REPLY,
69 MGMT_OP_USER_CONFIRM_NEG_REPLY,
70 MGMT_OP_USER_PASSKEY_REPLY,
71 MGMT_OP_USER_PASSKEY_NEG_REPLY,
72 MGMT_OP_READ_LOCAL_OOB_DATA,
73 MGMT_OP_ADD_REMOTE_OOB_DATA,
74 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
75 MGMT_OP_START_DISCOVERY,
76 MGMT_OP_STOP_DISCOVERY,
77 MGMT_OP_CONFIRM_NAME,
78 MGMT_OP_BLOCK_DEVICE,
79 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070080 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030081 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030082 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070083 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070084 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080085 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080086 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020087 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020088 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020089 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030090 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020091 MGMT_OP_ADD_DEVICE,
92 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030093 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020094 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020095 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020096 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020097 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010098 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020099};
100
101static const u16 mgmt_events[] = {
102 MGMT_EV_CONTROLLER_ERROR,
103 MGMT_EV_INDEX_ADDED,
104 MGMT_EV_INDEX_REMOVED,
105 MGMT_EV_NEW_SETTINGS,
106 MGMT_EV_CLASS_OF_DEV_CHANGED,
107 MGMT_EV_LOCAL_NAME_CHANGED,
108 MGMT_EV_NEW_LINK_KEY,
109 MGMT_EV_NEW_LONG_TERM_KEY,
110 MGMT_EV_DEVICE_CONNECTED,
111 MGMT_EV_DEVICE_DISCONNECTED,
112 MGMT_EV_CONNECT_FAILED,
113 MGMT_EV_PIN_CODE_REQUEST,
114 MGMT_EV_USER_CONFIRM_REQUEST,
115 MGMT_EV_USER_PASSKEY_REQUEST,
116 MGMT_EV_AUTH_FAILED,
117 MGMT_EV_DEVICE_FOUND,
118 MGMT_EV_DISCOVERING,
119 MGMT_EV_DEVICE_BLOCKED,
120 MGMT_EV_DEVICE_UNBLOCKED,
121 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300122 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800123 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700124 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200125 MGMT_EV_DEVICE_ADDED,
126 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300127 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200128 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200129 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200130 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200131};
132
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800133#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200134
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200135#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
136 "\x00\x00\x00\x00\x00\x00\x00\x00"
137
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200138struct mgmt_pending_cmd {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200140 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200141 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100142 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200143 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200144 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300145 void *user_data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200146 int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200147};
148
Johan Hedbergca69b792011-11-11 18:10:00 +0200149/* HCI to MGMT error code conversion table */
150static u8 mgmt_status_table[] = {
151 MGMT_STATUS_SUCCESS,
152 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
153 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
154 MGMT_STATUS_FAILED, /* Hardware Failure */
155 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
156 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200157 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200158 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
159 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
160 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
161 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
162 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
163 MGMT_STATUS_BUSY, /* Command Disallowed */
164 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
165 MGMT_STATUS_REJECTED, /* Rejected Security */
166 MGMT_STATUS_REJECTED, /* Rejected Personal */
167 MGMT_STATUS_TIMEOUT, /* Host Timeout */
168 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
169 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
170 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
171 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
172 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
173 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
174 MGMT_STATUS_BUSY, /* Repeated Attempts */
175 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
176 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
177 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
178 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
179 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
180 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
181 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
182 MGMT_STATUS_FAILED, /* Unspecified Error */
183 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
184 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
185 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
186 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
187 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
188 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
189 MGMT_STATUS_FAILED, /* Unit Link Key Used */
190 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
191 MGMT_STATUS_TIMEOUT, /* Instant Passed */
192 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
193 MGMT_STATUS_FAILED, /* Transaction Collision */
194 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
195 MGMT_STATUS_REJECTED, /* QoS Rejected */
196 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
197 MGMT_STATUS_REJECTED, /* Insufficient Security */
198 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
199 MGMT_STATUS_BUSY, /* Role Switch Pending */
200 MGMT_STATUS_FAILED, /* Slot Violation */
201 MGMT_STATUS_FAILED, /* Role Switch Failed */
202 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
203 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
204 MGMT_STATUS_BUSY, /* Host Busy Pairing */
205 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
206 MGMT_STATUS_BUSY, /* Controller Busy */
207 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
208 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
209 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
210 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
211 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
212};
213
214static u8 mgmt_status(u8 hci_status)
215{
216 if (hci_status < ARRAY_SIZE(mgmt_status_table))
217 return mgmt_status_table[hci_status];
218
219 return MGMT_STATUS_FAILED;
220}
221
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200222static int mgmt_send_event(u16 event, struct hci_dev *hdev,
223 unsigned short channel, void *data, u16 data_len,
224 struct sock *skip_sk)
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200225{
226 struct sk_buff *skb;
227 struct mgmt_hdr *hdr;
228
229 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
230 if (!skb)
231 return -ENOMEM;
232
233 hdr = (void *) skb_put(skb, sizeof(*hdr));
234 hdr->opcode = cpu_to_le16(event);
235 if (hdev)
236 hdr->index = cpu_to_le16(hdev->id);
237 else
238 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
239 hdr->len = cpu_to_le16(data_len);
240
241 if (data)
242 memcpy(skb_put(skb, data_len), data, data_len);
243
244 /* Time stamp */
245 __net_timestamp(skb);
246
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200247 hci_send_to_channel(channel, skb, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200248 kfree_skb(skb);
249
250 return 0;
251}
252
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200253static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
254 struct sock *skip_sk)
255{
256 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
257 skip_sk);
258}
259
Johan Hedberga69e8372015-03-06 21:08:53 +0200260static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200261{
262 struct sk_buff *skb;
263 struct mgmt_hdr *hdr;
264 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300265 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200266
Szymon Janc34eb5252011-02-28 14:10:08 +0100267 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200268
Andre Guedes790eff42012-06-07 19:05:46 -0300269 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200270 if (!skb)
271 return -ENOMEM;
272
273 hdr = (void *) skb_put(skb, sizeof(*hdr));
274
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100276 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200277 hdr->len = cpu_to_le16(sizeof(*ev));
278
279 ev = (void *) skb_put(skb, sizeof(*ev));
280 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200281 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200282
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 err = sock_queue_rcv_skb(sk, skb);
284 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200285 kfree_skb(skb);
286
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300287 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200288}
289
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200290static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
291 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200292{
293 struct sk_buff *skb;
294 struct mgmt_hdr *hdr;
295 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300296 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200297
298 BT_DBG("sock %p", sk);
299
Andre Guedes790eff42012-06-07 19:05:46 -0300300 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200301 if (!skb)
302 return -ENOMEM;
303
304 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200305
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700306 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100307 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200308 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200309
Johan Hedberga38528f2011-01-22 06:46:43 +0200310 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200311 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200312 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100313
314 if (rp)
315 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200316
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300317 err = sock_queue_rcv_skb(sk, skb);
318 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200319 kfree_skb(skb);
320
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100321 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200322}
323
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300324static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
325 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200326{
327 struct mgmt_rp_read_version rp;
328
329 BT_DBG("sock %p", sk);
330
331 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700332 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200333
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200334 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
335 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200336}
337
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300338static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
339 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200340{
341 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200342 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
343 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200344 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345 size_t rp_size;
346 int i, err;
347
348 BT_DBG("sock %p", sk);
349
350 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
351
352 rp = kmalloc(rp_size, GFP_KERNEL);
353 if (!rp)
354 return -ENOMEM;
355
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700356 rp->num_commands = cpu_to_le16(num_commands);
357 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200358
359 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
360 put_unaligned_le16(mgmt_commands[i], opcode);
361
362 for (i = 0; i < num_events; i++, opcode++)
363 put_unaligned_le16(mgmt_events[i], opcode);
364
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200365 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
366 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200367 kfree(rp);
368
369 return err;
370}
371
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300372static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
373 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200376 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200377 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200378 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300379 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200380
381 BT_DBG("sock %p", sk);
382
383 read_lock(&hci_dev_list_lock);
384
385 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300386 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200387 if (d->dev_type == HCI_BREDR &&
388 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700389 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200390 }
391
Johan Hedberga38528f2011-01-22 06:46:43 +0200392 rp_len = sizeof(*rp) + (2 * count);
393 rp = kmalloc(rp_len, GFP_ATOMIC);
394 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100395 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200396 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100397 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200398
Johan Hedberg476e44c2012-10-19 20:10:46 +0300399 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200400 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200401 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200402 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200403 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200404 continue;
405
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200406 /* Devices marked as raw-only are neither configured
407 * nor unconfigured controllers.
408 */
409 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700410 continue;
411
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200412 if (d->dev_type == HCI_BREDR &&
413 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700414 rp->index[count++] = cpu_to_le16(d->id);
415 BT_DBG("Added hci%u", d->id);
416 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417 }
418
Johan Hedberg476e44c2012-10-19 20:10:46 +0300419 rp->num_controllers = cpu_to_le16(count);
420 rp_len = sizeof(*rp) + (2 * count);
421
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200422 read_unlock(&hci_dev_list_lock);
423
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200424 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
425 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200426
Johan Hedberga38528f2011-01-22 06:46:43 +0200427 kfree(rp);
428
429 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200430}
431
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200432static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
433 void *data, u16 data_len)
434{
435 struct mgmt_rp_read_unconf_index_list *rp;
436 struct hci_dev *d;
437 size_t rp_len;
438 u16 count;
439 int err;
440
441 BT_DBG("sock %p", sk);
442
443 read_lock(&hci_dev_list_lock);
444
445 count = 0;
446 list_for_each_entry(d, &hci_dev_list, list) {
447 if (d->dev_type == HCI_BREDR &&
448 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
449 count++;
450 }
451
452 rp_len = sizeof(*rp) + (2 * count);
453 rp = kmalloc(rp_len, GFP_ATOMIC);
454 if (!rp) {
455 read_unlock(&hci_dev_list_lock);
456 return -ENOMEM;
457 }
458
459 count = 0;
460 list_for_each_entry(d, &hci_dev_list, list) {
461 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200462 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200463 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
464 continue;
465
466 /* Devices marked as raw-only are neither configured
467 * nor unconfigured controllers.
468 */
469 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
470 continue;
471
472 if (d->dev_type == HCI_BREDR &&
473 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
474 rp->index[count++] = cpu_to_le16(d->id);
475 BT_DBG("Added hci%u", d->id);
476 }
477 }
478
479 rp->num_controllers = cpu_to_le16(count);
480 rp_len = sizeof(*rp) + (2 * count);
481
482 read_unlock(&hci_dev_list_lock);
483
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200484 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
485 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200486
487 kfree(rp);
488
489 return err;
490}
491
Marcel Holtmanndbece372014-07-04 18:11:55 +0200492static bool is_configured(struct hci_dev *hdev)
493{
494 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
495 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
496 return false;
497
498 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
499 !bacmp(&hdev->public_addr, BDADDR_ANY))
500 return false;
501
502 return true;
503}
504
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200505static __le32 get_missing_options(struct hci_dev *hdev)
506{
507 u32 options = 0;
508
Marcel Holtmanndbece372014-07-04 18:11:55 +0200509 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
510 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200511 options |= MGMT_OPTION_EXTERNAL_CONFIG;
512
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200513 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
514 !bacmp(&hdev->public_addr, BDADDR_ANY))
515 options |= MGMT_OPTION_PUBLIC_ADDRESS;
516
517 return cpu_to_le32(options);
518}
519
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200520static int new_options(struct hci_dev *hdev, struct sock *skip)
521{
522 __le32 options = get_missing_options(hdev);
523
524 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
525 sizeof(options), skip);
526}
527
Marcel Holtmanndbece372014-07-04 18:11:55 +0200528static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
529{
530 __le32 options = get_missing_options(hdev);
531
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200532 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
533 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200534}
535
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200536static int read_config_info(struct sock *sk, struct hci_dev *hdev,
537 void *data, u16 data_len)
538{
539 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200541
542 BT_DBG("sock %p %s", sk, hdev->name);
543
544 hci_dev_lock(hdev);
545
546 memset(&rp, 0, sizeof(rp));
547 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200548
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200549 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
550 options |= MGMT_OPTION_EXTERNAL_CONFIG;
551
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200552 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200553 options |= MGMT_OPTION_PUBLIC_ADDRESS;
554
555 rp.supported_options = cpu_to_le32(options);
556 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200557
558 hci_dev_unlock(hdev);
559
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200560 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
561 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200562}
563
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200565{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200566 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200567
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200568 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300569 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800570 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300571 settings |= MGMT_SETTING_CONNECTABLE;
572 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200573
Andre Guedesed3fa312012-07-24 15:03:46 -0300574 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500575 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
576 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200577 settings |= MGMT_SETTING_BREDR;
578 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700579
580 if (lmp_ssp_capable(hdev)) {
581 settings |= MGMT_SETTING_SSP;
582 settings |= MGMT_SETTING_HS;
583 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800584
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800585 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800586 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700587 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100588
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300589 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200590 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300591 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300592 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200593 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800594 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300595 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200596
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200597 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
598 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200599 settings |= MGMT_SETTING_CONFIGURATION;
600
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200601 return settings;
602}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200603
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604static u32 get_current_settings(struct hci_dev *hdev)
605{
606 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200607
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200608 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100609 settings |= MGMT_SETTING_POWERED;
610
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200611 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200612 settings |= MGMT_SETTING_CONNECTABLE;
613
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500614 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
615 settings |= MGMT_SETTING_FAST_CONNECTABLE;
616
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200617 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_DISCOVERABLE;
619
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300620 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300621 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200622
Johan Hedberg56f87902013-10-02 13:43:13 +0300623 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200624 settings |= MGMT_SETTING_BREDR;
625
Johan Hedberg06199cf2012-02-22 16:37:11 +0200626 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200627 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200628
Johan Hedberg47990ea2012-02-22 11:58:37 +0200629 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200630 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200631
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200632 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200633 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200634
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200635 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
636 settings |= MGMT_SETTING_HS;
637
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200638 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300639 settings |= MGMT_SETTING_ADVERTISING;
640
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800641 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
642 settings |= MGMT_SETTING_SECURE_CONN;
643
Johan Hedberg0663b292014-06-24 13:15:50 +0300644 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800645 settings |= MGMT_SETTING_DEBUG_KEYS;
646
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200647 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
648 settings |= MGMT_SETTING_PRIVACY;
649
Marcel Holtmann93690c22015-03-06 10:11:21 -0800650 /* The current setting for static address has two purposes. The
651 * first is to indicate if the static address will be used and
652 * the second is to indicate if it is actually set.
653 *
654 * This means if the static address is not configured, this flag
655 * will never bet set. If the address is configured, then if the
656 * address is actually used decides if the flag is set or not.
657 *
658 * For single mode LE only controllers and dual-mode controllers
659 * with BR/EDR disabled, the existence of the static address will
660 * be evaluated.
661 */
662 if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ||
663 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
664 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
665 if (bacmp(&hdev->static_addr, BDADDR_ANY))
666 settings |= MGMT_SETTING_STATIC_ADDRESS;
667 }
668
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200669 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200670}
671
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300672#define PNP_INFO_SVCLASS_ID 0x1200
673
Johan Hedberg213202e2013-01-27 00:31:33 +0200674static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
675{
676 u8 *ptr = data, *uuids_start = NULL;
677 struct bt_uuid *uuid;
678
679 if (len < 4)
680 return ptr;
681
682 list_for_each_entry(uuid, &hdev->uuids, list) {
683 u16 uuid16;
684
685 if (uuid->size != 16)
686 continue;
687
688 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
689 if (uuid16 < 0x1100)
690 continue;
691
692 if (uuid16 == PNP_INFO_SVCLASS_ID)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID16_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u16) > len) {
704 uuids_start[1] = EIR_UUID16_SOME;
705 break;
706 }
707
708 *ptr++ = (uuid16 & 0x00ff);
709 *ptr++ = (uuid16 & 0xff00) >> 8;
710 uuids_start[0] += sizeof(uuid16);
711 }
712
713 return ptr;
714}
715
Johan Hedbergcdf19632013-01-27 00:31:34 +0200716static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 6)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 32)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID32_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + sizeof(u32) > len) {
737 uuids_start[1] = EIR_UUID32_SOME;
738 break;
739 }
740
741 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
742 ptr += sizeof(u32);
743 uuids_start[0] += sizeof(u32);
744 }
745
746 return ptr;
747}
748
Johan Hedbergc00d5752013-01-27 00:31:35 +0200749static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
750{
751 u8 *ptr = data, *uuids_start = NULL;
752 struct bt_uuid *uuid;
753
754 if (len < 18)
755 return ptr;
756
757 list_for_each_entry(uuid, &hdev->uuids, list) {
758 if (uuid->size != 128)
759 continue;
760
761 if (!uuids_start) {
762 uuids_start = ptr;
763 uuids_start[0] = 1;
764 uuids_start[1] = EIR_UUID128_ALL;
765 ptr += 2;
766 }
767
768 /* Stop if not enough space to put next UUID */
769 if ((ptr - data) + 16 > len) {
770 uuids_start[1] = EIR_UUID128_SOME;
771 break;
772 }
773
774 memcpy(ptr, uuid->uuid, 16);
775 ptr += 16;
776 uuids_start[0] += 16;
777 }
778
779 return ptr;
780}
781
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200782static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
783 struct hci_dev *hdev)
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300784{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200785 struct mgmt_pending_cmd *cmd;
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300786
787 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
788 if (cmd->opcode == opcode)
789 return cmd;
790 }
791
792 return NULL;
793}
794
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200795static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
796 struct hci_dev *hdev,
797 const void *data)
Johan Hedberg95868422014-06-28 17:54:07 +0300798{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200799 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +0300800
801 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
802 if (cmd->user_data != data)
803 continue;
804 if (cmd->opcode == opcode)
805 return cmd;
806 }
807
808 return NULL;
809}
810
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
812{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700813 u8 ad_len = 0;
814 size_t name_len;
815
816 name_len = strlen(hdev->dev_name);
817 if (name_len > 0) {
818 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
819
820 if (name_len > max_len) {
821 name_len = max_len;
822 ptr[1] = EIR_NAME_SHORT;
823 } else
824 ptr[1] = EIR_NAME_COMPLETE;
825
826 ptr[0] = name_len + 1;
827
828 memcpy(ptr + 2, hdev->dev_name, name_len);
829
830 ad_len += (name_len + 2);
831 ptr += (name_len + 2);
832 }
833
834 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700835}
836
837static void update_scan_rsp_data(struct hci_request *req)
838{
839 struct hci_dev *hdev = req->hdev;
840 struct hci_cp_le_set_scan_rsp_data cp;
841 u8 len;
842
Johan Hedberg7751ef12013-10-19 23:38:15 +0300843 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700844 return;
845
846 memset(&cp, 0, sizeof(cp));
847
848 len = create_scan_rsp_data(hdev, cp.data);
849
Johan Hedbergeb438b52013-10-16 15:31:07 +0300850 if (hdev->scan_rsp_data_len == len &&
851 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700852 return;
853
Johan Hedbergeb438b52013-10-16 15:31:07 +0300854 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
855 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700856
857 cp.length = len;
858
859 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
860}
861
Johan Hedberg9a43e252013-10-20 19:00:07 +0300862static u8 get_adv_discov_flags(struct hci_dev *hdev)
863{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200864 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300865
866 /* If there's a pending mgmt command the flags will not yet have
867 * their final values, so check for this first.
868 */
869 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
870 if (cmd) {
871 struct mgmt_mode *cp = cmd->param;
872 if (cp->val == 0x01)
873 return LE_AD_GENERAL;
874 else if (cp->val == 0x02)
875 return LE_AD_LIMITED;
876 } else {
877 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
878 return LE_AD_LIMITED;
879 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
880 return LE_AD_GENERAL;
881 }
882
883 return 0;
884}
885
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700886static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700887{
888 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700889
Johan Hedberg9a43e252013-10-20 19:00:07 +0300890 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891
Johan Hedberge8340042014-01-30 11:16:50 -0800892 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700893 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700894
895 if (flags) {
896 BT_DBG("adv flags 0x%02x", flags);
897
898 ptr[0] = 2;
899 ptr[1] = EIR_FLAGS;
900 ptr[2] = flags;
901
902 ad_len += 3;
903 ptr += 3;
904 }
905
906 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
907 ptr[0] = 2;
908 ptr[1] = EIR_TX_POWER;
909 ptr[2] = (u8) hdev->adv_tx_power;
910
911 ad_len += 3;
912 ptr += 3;
913 }
914
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700915 return ad_len;
916}
917
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700918static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700919{
920 struct hci_dev *hdev = req->hdev;
921 struct hci_cp_le_set_adv_data cp;
922 u8 len;
923
Johan Hedberg10994ce2013-10-19 23:38:16 +0300924 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700925 return;
926
927 memset(&cp, 0, sizeof(cp));
928
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700929 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700930
931 if (hdev->adv_data_len == len &&
932 memcmp(cp.data, hdev->adv_data, len) == 0)
933 return;
934
935 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
936 hdev->adv_data_len = len;
937
938 cp.length = len;
939
940 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
941}
942
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300943int mgmt_update_adv_data(struct hci_dev *hdev)
944{
945 struct hci_request req;
946
947 hci_req_init(&req, hdev);
948 update_adv_data(&req);
949
950 return hci_req_run(&req, NULL);
951}
952
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300953static void create_eir(struct hci_dev *hdev, u8 *data)
954{
955 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300956 size_t name_len;
957
958 name_len = strlen(hdev->dev_name);
959
960 if (name_len > 0) {
961 /* EIR Data type */
962 if (name_len > 48) {
963 name_len = 48;
964 ptr[1] = EIR_NAME_SHORT;
965 } else
966 ptr[1] = EIR_NAME_COMPLETE;
967
968 /* EIR Data length */
969 ptr[0] = name_len + 1;
970
971 memcpy(ptr + 2, hdev->dev_name, name_len);
972
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973 ptr += (name_len + 2);
974 }
975
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100976 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700977 ptr[0] = 2;
978 ptr[1] = EIR_TX_POWER;
979 ptr[2] = (u8) hdev->inq_tx_power;
980
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700981 ptr += 3;
982 }
983
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700984 if (hdev->devid_source > 0) {
985 ptr[0] = 9;
986 ptr[1] = EIR_DEVICE_ID;
987
988 put_unaligned_le16(hdev->devid_source, ptr + 2);
989 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
990 put_unaligned_le16(hdev->devid_product, ptr + 6);
991 put_unaligned_le16(hdev->devid_version, ptr + 8);
992
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700993 ptr += 10;
994 }
995
Johan Hedberg213202e2013-01-27 00:31:33 +0200996 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200997 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200998 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300999}
1000
Johan Hedberg890ea892013-03-15 17:06:52 -05001001static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001002{
Johan Hedberg890ea892013-03-15 17:06:52 -05001003 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001004 struct hci_cp_write_eir cp;
1005
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001006 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001007 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001008
Johan Hedberg976eb202012-10-24 21:12:01 +03001009 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001011
Johan Hedberg84bde9d2012-01-25 14:21:06 +02001012 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001013 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001014
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001015 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001017
1018 memset(&cp, 0, sizeof(cp));
1019
1020 create_eir(hdev, cp.data);
1021
1022 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001024
1025 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1026
Johan Hedberg890ea892013-03-15 17:06:52 -05001027 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001028}
1029
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030static u8 get_service_classes(struct hci_dev *hdev)
1031{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001032 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033 u8 val = 0;
1034
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001035 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001036 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001037
1038 return val;
1039}
1040
Johan Hedberg890ea892013-03-15 17:06:52 -05001041static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001042{
Johan Hedberg890ea892013-03-15 17:06:52 -05001043 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001044 u8 cod[3];
1045
1046 BT_DBG("%s", hdev->name);
1047
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001048 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001049 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001050
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001051 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1052 return;
1053
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001054 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001055 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001056
1057 cod[0] = hdev->minor_class;
1058 cod[1] = hdev->major_class;
1059 cod[2] = get_service_classes(hdev);
1060
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001061 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1062 cod[1] |= 0x20;
1063
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001064 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001065 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001066
Johan Hedberg890ea892013-03-15 17:06:52 -05001067 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001068}
1069
Johan Hedberga4858cb2014-02-25 19:56:31 +02001070static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001071{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001072 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001073
1074 /* If there's a pending mgmt command the flag will not yet have
1075 * it's final value, so check for this first.
1076 */
1077 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1078 if (cmd) {
1079 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001081 }
1082
Johan Hedberga4858cb2014-02-25 19:56:31 +02001083 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001084}
1085
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001086static void disable_advertising(struct hci_request *req)
1087{
1088 u8 enable = 0x00;
1089
1090 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1091}
1092
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001093static void enable_advertising(struct hci_request *req)
1094{
1095 struct hci_dev *hdev = req->hdev;
1096 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001097 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001098 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001099
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001100 if (hci_conn_num(hdev, LE_LINK) > 0)
1101 return;
1102
1103 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1104 disable_advertising(req);
1105
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001106 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001107 * hci_update_random_address knows that it's safe to go ahead
1108 * and write a new random address. The flag will be set back on
1109 * as soon as the SET_ADV_ENABLE HCI command completes.
1110 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001111 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001112
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001113 if (test_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags))
1114 connectable = true;
1115 else
1116 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001117
Johan Hedberga4858cb2014-02-25 19:56:31 +02001118 /* Set require_privacy to true only when non-connectable
1119 * advertising is used. In that case it is fine to use a
1120 * non-resolvable private address.
1121 */
1122 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001123 return;
1124
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001125 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001126 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1127 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001128 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001129 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001130 cp.channel_map = hdev->le_adv_channel_map;
1131
1132 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1133
1134 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1135}
1136
Johan Hedberg7d785252011-12-15 00:47:39 +02001137static void service_cache_off(struct work_struct *work)
1138{
1139 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001140 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001141 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001142
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001143 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001144 return;
1145
Johan Hedberg890ea892013-03-15 17:06:52 -05001146 hci_req_init(&req, hdev);
1147
Johan Hedberg7d785252011-12-15 00:47:39 +02001148 hci_dev_lock(hdev);
1149
Johan Hedberg890ea892013-03-15 17:06:52 -05001150 update_eir(&req);
1151 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001152
1153 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001154
1155 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001156}
1157
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001158static void rpa_expired(struct work_struct *work)
1159{
1160 struct hci_dev *hdev = container_of(work, struct hci_dev,
1161 rpa_expired.work);
1162 struct hci_request req;
1163
1164 BT_DBG("");
1165
1166 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1167
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001168 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001169 return;
1170
1171 /* The generation of a new RPA and programming it into the
1172 * controller happens in the enable_advertising() function.
1173 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001174 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001175 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001176 hci_req_run(&req, NULL);
1177}
1178
Johan Hedberg6a919082012-02-28 06:17:26 +02001179static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001180{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001181 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001182 return;
1183
Johan Hedberg4f87da82012-03-02 19:55:56 +02001184 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001185 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001186
Johan Hedberg4f87da82012-03-02 19:55:56 +02001187 /* Non-mgmt controlled devices get this bit set
1188 * implicitly so that pairing works for them, however
1189 * for mgmt we require user-space to explicitly enable
1190 * it
1191 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001192 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001193}
1194
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001195static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001196 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001197{
1198 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001199
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001200 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001201
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001202 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001203
Johan Hedberg03811012010-12-08 00:21:06 +02001204 memset(&rp, 0, sizeof(rp));
1205
Johan Hedberg03811012010-12-08 00:21:06 +02001206 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001207
1208 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001209 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001210
1211 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1212 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1213
1214 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001215
1216 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001217 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001218
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001219 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001220
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001221 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1222 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001223}
1224
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001225static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001226{
1227 sock_put(cmd->sk);
1228 kfree(cmd->param);
1229 kfree(cmd);
1230}
1231
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001232static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
1233 struct hci_dev *hdev,
1234 void *data, u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001235{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001236 struct mgmt_pending_cmd *cmd;
Johan Hedberg03811012010-12-08 00:21:06 +02001237
Johan Hedbergfca20012014-06-28 17:54:05 +03001238 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001239 if (!cmd)
1240 return NULL;
1241
1242 cmd->opcode = opcode;
1243 cmd->index = hdev->id;
1244
Johan Hedberg323b0b82014-12-05 13:36:01 +02001245 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001246 if (!cmd->param) {
1247 kfree(cmd);
1248 return NULL;
1249 }
1250
Johan Hedberg323b0b82014-12-05 13:36:01 +02001251 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001252
1253 cmd->sk = sk;
1254 sock_hold(sk);
1255
1256 list_add(&cmd->list, &hdev->mgmt_pending);
1257
1258 return cmd;
1259}
1260
1261static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001262 void (*cb)(struct mgmt_pending_cmd *cmd,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001263 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001264 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001265{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001266 struct mgmt_pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001267
Andre Guedesa3d09352013-02-01 11:21:30 -03001268 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001269 if (opcode > 0 && cmd->opcode != opcode)
1270 continue;
1271
1272 cb(cmd, data);
1273 }
1274}
1275
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001276static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001277{
1278 list_del(&cmd->list);
1279 mgmt_pending_free(cmd);
1280}
1281
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001282static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001283{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001284 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001285
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001286 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1287 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001288}
1289
Marcel Holtmann1904a852015-01-11 13:50:44 -08001290static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001291{
1292 BT_DBG("%s status 0x%02x", hdev->name, status);
1293
Johan Hedberga3172b72014-02-28 09:33:44 +02001294 if (hci_conn_count(hdev) == 0) {
1295 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001296 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001297 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001298}
1299
Johan Hedberg23a48092014-07-08 16:05:06 +03001300static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001301{
1302 struct hci_dev *hdev = req->hdev;
1303 struct hci_cp_remote_name_req_cancel cp;
1304 struct inquiry_entry *e;
1305
1306 switch (hdev->discovery.state) {
1307 case DISCOVERY_FINDING:
1308 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1309 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1310 } else {
1311 cancel_delayed_work(&hdev->le_scan_disable);
1312 hci_req_add_le_scan_disable(req);
1313 }
1314
Johan Hedberg23a48092014-07-08 16:05:06 +03001315 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001316
1317 case DISCOVERY_RESOLVING:
1318 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1319 NAME_PENDING);
1320 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001321 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001322
1323 bacpy(&cp.bdaddr, &e->data.bdaddr);
1324 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1325 &cp);
1326
Johan Hedberg23a48092014-07-08 16:05:06 +03001327 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001328
1329 default:
1330 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001331 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001332 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001333 return true;
1334 }
1335
Johan Hedberg21a60d32014-06-10 14:05:58 +03001336 break;
1337 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001338
1339 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001340}
1341
Johan Hedberg8b064a32014-02-24 14:52:22 +02001342static int clean_up_hci_state(struct hci_dev *hdev)
1343{
1344 struct hci_request req;
1345 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001346 bool discov_stopped;
1347 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001348
1349 hci_req_init(&req, hdev);
1350
1351 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1352 test_bit(HCI_PSCAN, &hdev->flags)) {
1353 u8 scan = 0x00;
1354 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1355 }
1356
Johan Hedberg73e082f2014-07-08 15:07:51 +03001357 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001358 disable_advertising(&req);
1359
Johan Hedberg23a48092014-07-08 16:05:06 +03001360 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001361
1362 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1363 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001364 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001365
Johan Hedbergc9910d02014-02-27 14:35:12 +02001366 switch (conn->state) {
1367 case BT_CONNECTED:
1368 case BT_CONFIG:
1369 dc.handle = cpu_to_le16(conn->handle);
1370 dc.reason = 0x15; /* Terminated due to Power Off */
1371 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1372 break;
1373 case BT_CONNECT:
1374 if (conn->type == LE_LINK)
1375 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1376 0, NULL);
1377 else if (conn->type == ACL_LINK)
1378 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1379 6, &conn->dst);
1380 break;
1381 case BT_CONNECT2:
1382 bacpy(&rej.bdaddr, &conn->dst);
1383 rej.reason = 0x15; /* Terminated due to Power Off */
1384 if (conn->type == ACL_LINK)
1385 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1386 sizeof(rej), &rej);
1387 else if (conn->type == SCO_LINK)
1388 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1389 sizeof(rej), &rej);
1390 break;
1391 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001392 }
1393
Johan Hedberg23a48092014-07-08 16:05:06 +03001394 err = hci_req_run(&req, clean_up_hci_complete);
1395 if (!err && discov_stopped)
1396 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1397
1398 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001399}
1400
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001401static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001402 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001403{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001404 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001405 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001406 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001407
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001408 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001409
Johan Hedberga7e80f22013-01-09 16:05:19 +02001410 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001411 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1412 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001413
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001414 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001415
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001416 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001417 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1418 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001419 goto failed;
1420 }
1421
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001422 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1423 cancel_delayed_work(&hdev->power_off);
1424
1425 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001426 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1427 data, len);
1428 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001429 goto failed;
1430 }
1431 }
1432
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001433 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001434 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001435 goto failed;
1436 }
1437
Johan Hedberg03811012010-12-08 00:21:06 +02001438 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1439 if (!cmd) {
1440 err = -ENOMEM;
1441 goto failed;
1442 }
1443
Johan Hedberg8b064a32014-02-24 14:52:22 +02001444 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001445 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001446 err = 0;
1447 } else {
1448 /* Disconnect connections, stop scans, etc */
1449 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001450 if (!err)
1451 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1452 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001453
Johan Hedberg8b064a32014-02-24 14:52:22 +02001454 /* ENODATA means there were no HCI commands queued */
1455 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001456 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001457 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1458 err = 0;
1459 }
1460 }
Johan Hedberg03811012010-12-08 00:21:06 +02001461
1462failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001463 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001464 return err;
1465}
1466
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001467static int new_settings(struct hci_dev *hdev, struct sock *skip)
1468{
1469 __le32 ev;
1470
1471 ev = cpu_to_le32(get_current_settings(hdev));
1472
1473 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1474}
1475
Johan Hedberg91a668b2014-07-09 13:28:26 +03001476int mgmt_new_settings(struct hci_dev *hdev)
1477{
1478 return new_settings(hdev, NULL);
1479}
1480
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001481struct cmd_lookup {
1482 struct sock *sk;
1483 struct hci_dev *hdev;
1484 u8 mgmt_status;
1485};
1486
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001487static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001488{
1489 struct cmd_lookup *match = data;
1490
1491 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1492
1493 list_del(&cmd->list);
1494
1495 if (match->sk == NULL) {
1496 match->sk = cmd->sk;
1497 sock_hold(match->sk);
1498 }
1499
1500 mgmt_pending_free(cmd);
1501}
1502
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001503static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001504{
1505 u8 *status = data;
1506
Johan Hedberga69e8372015-03-06 21:08:53 +02001507 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001508 mgmt_pending_remove(cmd);
1509}
1510
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001511static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001512{
1513 if (cmd->cmd_complete) {
1514 u8 *status = data;
1515
1516 cmd->cmd_complete(cmd, *status);
1517 mgmt_pending_remove(cmd);
1518
1519 return;
1520 }
1521
1522 cmd_status_rsp(cmd, data);
1523}
1524
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001525static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001526{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001527 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1528 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001529}
1530
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001531static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001532{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001533 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1534 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001535}
1536
Johan Hedberge6fe7982013-10-02 15:45:22 +03001537static u8 mgmt_bredr_support(struct hci_dev *hdev)
1538{
1539 if (!lmp_bredr_capable(hdev))
1540 return MGMT_STATUS_NOT_SUPPORTED;
1541 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1542 return MGMT_STATUS_REJECTED;
1543 else
1544 return MGMT_STATUS_SUCCESS;
1545}
1546
1547static u8 mgmt_le_support(struct hci_dev *hdev)
1548{
1549 if (!lmp_le_capable(hdev))
1550 return MGMT_STATUS_NOT_SUPPORTED;
1551 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1552 return MGMT_STATUS_REJECTED;
1553 else
1554 return MGMT_STATUS_SUCCESS;
1555}
1556
Marcel Holtmann1904a852015-01-11 13:50:44 -08001557static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1558 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001559{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001560 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001561 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001562 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001563 bool changed;
1564
1565 BT_DBG("status 0x%02x", status);
1566
1567 hci_dev_lock(hdev);
1568
1569 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1570 if (!cmd)
1571 goto unlock;
1572
1573 if (status) {
1574 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001575 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001576 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001577 goto remove_cmd;
1578 }
1579
1580 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001581 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001582 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1583 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001584
1585 if (hdev->discov_timeout > 0) {
1586 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1587 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1588 to);
1589 }
1590 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001591 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1592 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001593 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001594
1595 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1596
1597 if (changed)
1598 new_settings(hdev, cmd->sk);
1599
Marcel Holtmann970ba522013-10-15 06:33:57 -07001600 /* When the discoverable mode gets changed, make sure
1601 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001602 * bit correctly set. Also update page scan based on whitelist
1603 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001604 */
1605 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001606 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001607 update_class(&req);
1608 hci_req_run(&req, NULL);
1609
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001610remove_cmd:
1611 mgmt_pending_remove(cmd);
1612
1613unlock:
1614 hci_dev_unlock(hdev);
1615}
1616
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001617static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001618 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001619{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001620 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001621 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001622 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001623 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001624 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001625 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001626
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001628
Johan Hedberg9a43e252013-10-20 19:00:07 +03001629 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1630 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02001631 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1632 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001633
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001634 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001635 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1636 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001637
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001638 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001639
1640 /* Disabling discoverable requires that no timeout is set,
1641 * and enabling limited discoverable requires a timeout.
1642 */
1643 if ((cp->val == 0x00 && timeout > 0) ||
1644 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001645 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1646 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001647
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001648 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001649
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001650 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001651 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1652 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001653 goto failed;
1654 }
1655
1656 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001657 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001658 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1659 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001660 goto failed;
1661 }
1662
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001663 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001664 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1665 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001666 goto failed;
1667 }
1668
1669 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001670 bool changed = false;
1671
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001672 /* Setting limited discoverable when powered off is
1673 * not a valid operation since it requires a timeout
1674 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1675 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001676 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1677 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1678 changed = true;
1679 }
1680
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001681 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001682 if (err < 0)
1683 goto failed;
1684
1685 if (changed)
1686 err = new_settings(hdev, sk);
1687
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001688 goto failed;
1689 }
1690
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001691 /* If the current mode is the same, then just update the timeout
1692 * value with the new value. And if only the timeout gets updated,
1693 * then no need for any HCI transactions.
1694 */
1695 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1696 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1697 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001698 cancel_delayed_work(&hdev->discov_off);
1699 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001700
Marcel Holtmann36261542013-10-15 08:28:51 -07001701 if (cp->val && hdev->discov_timeout > 0) {
1702 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001703 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001704 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001705 }
1706
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001707 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001708 goto failed;
1709 }
1710
1711 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1712 if (!cmd) {
1713 err = -ENOMEM;
1714 goto failed;
1715 }
1716
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 /* Cancel any potential discoverable timeout that might be
1718 * still active and store new timeout value. The arming of
1719 * the timeout happens in the complete handler.
1720 */
1721 cancel_delayed_work(&hdev->discov_off);
1722 hdev->discov_timeout = timeout;
1723
Johan Hedbergb456f872013-10-19 23:38:22 +03001724 /* Limited discoverable mode */
1725 if (cp->val == 0x02)
1726 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1727 else
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001730 hci_req_init(&req, hdev);
1731
Johan Hedberg9a43e252013-10-20 19:00:07 +03001732 /* The procedure for LE-only controllers is much simpler - just
1733 * update the advertising data.
1734 */
1735 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1736 goto update_ad;
1737
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001738 scan = SCAN_PAGE;
1739
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001740 if (cp->val) {
1741 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001742
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001743 if (cp->val == 0x02) {
1744 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001745 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001746 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1747 hci_cp.iac_lap[1] = 0x8b;
1748 hci_cp.iac_lap[2] = 0x9e;
1749 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1750 hci_cp.iac_lap[4] = 0x8b;
1751 hci_cp.iac_lap[5] = 0x9e;
1752 } else {
1753 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001754 hci_cp.num_iac = 1;
1755 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1756 hci_cp.iac_lap[1] = 0x8b;
1757 hci_cp.iac_lap[2] = 0x9e;
1758 }
1759
1760 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1761 (hci_cp.num_iac * 3) + 1, &hci_cp);
1762
1763 scan |= SCAN_INQUIRY;
1764 } else {
1765 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1766 }
1767
1768 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001769
Johan Hedberg9a43e252013-10-20 19:00:07 +03001770update_ad:
1771 update_adv_data(&req);
1772
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001773 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001774 if (err < 0)
1775 mgmt_pending_remove(cmd);
1776
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001777failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001778 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001779 return err;
1780}
1781
Johan Hedberg406d7802013-03-15 17:07:09 -05001782static void write_fast_connectable(struct hci_request *req, bool enable)
1783{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001784 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001785 struct hci_cp_write_page_scan_activity acp;
1786 u8 type;
1787
Johan Hedberg547003b2013-10-21 16:51:53 +03001788 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1789 return;
1790
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001791 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1792 return;
1793
Johan Hedberg406d7802013-03-15 17:07:09 -05001794 if (enable) {
1795 type = PAGE_SCAN_TYPE_INTERLACED;
1796
1797 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001798 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001799 } else {
1800 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1801
1802 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001803 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001804 }
1805
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001806 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001807
Johan Hedbergbd98b992013-03-15 17:07:13 -05001808 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1809 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1810 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1811 sizeof(acp), &acp);
1812
1813 if (hdev->page_scan_type != type)
1814 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001815}
1816
Marcel Holtmann1904a852015-01-11 13:50:44 -08001817static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1818 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001819{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001820 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001822 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823
1824 BT_DBG("status 0x%02x", status);
1825
1826 hci_dev_lock(hdev);
1827
1828 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1829 if (!cmd)
1830 goto unlock;
1831
Johan Hedberg37438c12013-10-14 16:20:05 +03001832 if (status) {
1833 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001834 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001835 goto remove_cmd;
1836 }
1837
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001838 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001839 if (cp->val) {
1840 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1841 &hdev->dev_flags);
1842 discov_changed = false;
1843 } else {
1844 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1845 &hdev->dev_flags);
1846 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1847 &hdev->dev_flags);
1848 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001849
Johan Hedberg2b76f452013-03-15 17:07:04 -05001850 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1851
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001852 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001853 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001854 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001855 if (discov_changed)
1856 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001857 hci_update_background_scan(hdev);
1858 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001859
Johan Hedberg37438c12013-10-14 16:20:05 +03001860remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001861 mgmt_pending_remove(cmd);
1862
1863unlock:
1864 hci_dev_unlock(hdev);
1865}
1866
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001867static int set_connectable_update_settings(struct hci_dev *hdev,
1868 struct sock *sk, u8 val)
1869{
1870 bool changed = false;
1871 int err;
1872
1873 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1874 changed = true;
1875
1876 if (val) {
1877 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1878 } else {
1879 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1880 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1881 }
1882
1883 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1884 if (err < 0)
1885 return err;
1886
Johan Hedberg562064e2014-07-08 16:35:34 +03001887 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001888 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001889 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001890 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001891 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001892
1893 return 0;
1894}
1895
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001896static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001897 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001898{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001899 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001900 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001901 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001902 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001903 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001904
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001905 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001906
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001907 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1908 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02001909 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1910 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001911
Johan Hedberga7e80f22013-01-09 16:05:19 +02001912 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001913 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1914 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001915
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001916 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001917
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001918 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001919 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001920 goto failed;
1921 }
1922
1923 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001924 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001925 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1926 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001927 goto failed;
1928 }
1929
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001930 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1931 if (!cmd) {
1932 err = -ENOMEM;
1933 goto failed;
1934 }
1935
Johan Hedberg2b76f452013-03-15 17:07:04 -05001936 hci_req_init(&req, hdev);
1937
Johan Hedberg9a43e252013-10-20 19:00:07 +03001938 /* If BR/EDR is not enabled and we disable advertising as a
1939 * by-product of disabling connectable, we need to update the
1940 * advertising flags.
1941 */
1942 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1943 if (!cp->val) {
1944 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1945 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1946 }
1947 update_adv_data(&req);
1948 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001949 if (cp->val) {
1950 scan = SCAN_PAGE;
1951 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001952 /* If we don't have any whitelist entries just
1953 * disable all scanning. If there are entries
1954 * and we had both page and inquiry scanning
1955 * enabled then fall back to only page scanning.
1956 * Otherwise no changes are needed.
1957 */
1958 if (list_empty(&hdev->whitelist))
1959 scan = SCAN_DISABLED;
1960 else if (test_bit(HCI_ISCAN, &hdev->flags))
1961 scan = SCAN_PAGE;
1962 else
1963 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001964
1965 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001966 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001967 cancel_delayed_work(&hdev->discov_off);
1968 }
1969
1970 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1971 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001972
Johan Hedberg3bd27242014-07-28 20:53:58 +03001973no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03001974 /* Update the advertising parameters if necessary */
1975 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001976 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001977
Johan Hedberg2b76f452013-03-15 17:07:04 -05001978 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001979 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001981 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001982 err = set_connectable_update_settings(hdev, sk,
1983 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001984 goto failed;
1985 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
1987failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001988 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989 return err;
1990}
1991
Johan Hedbergb2939472014-07-30 09:22:23 +03001992static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001993 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001994{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001995 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001996 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001997 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001998
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001999 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002000
Johan Hedberga7e80f22013-01-09 16:05:19 +02002001 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002002 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2003 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002004
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002005 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002006
2007 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002008 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002009 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002010 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002011
Johan Hedbergb2939472014-07-30 09:22:23 +03002012 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002013 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002014 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002015
Marcel Holtmann55594352013-10-06 16:11:57 -07002016 if (changed)
2017 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002018
Marcel Holtmann55594352013-10-06 16:11:57 -07002019unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002020 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002021 return err;
2022}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002023
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002024static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2025 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002026{
2027 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002028 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002029 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002030 int err;
2031
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002032 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002033
Johan Hedberge6fe7982013-10-02 15:45:22 +03002034 status = mgmt_bredr_support(hdev);
2035 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002036 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2037 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002038
Johan Hedberga7e80f22013-01-09 16:05:19 +02002039 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002040 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2041 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002042
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002043 hci_dev_lock(hdev);
2044
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002045 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002046 bool changed = false;
2047
2048 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002049 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002050 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2051 changed = true;
2052 }
2053
2054 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2055 if (err < 0)
2056 goto failed;
2057
2058 if (changed)
2059 err = new_settings(hdev, sk);
2060
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002061 goto failed;
2062 }
2063
2064 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002065 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2066 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002067 goto failed;
2068 }
2069
2070 val = !!cp->val;
2071
2072 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2073 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2074 goto failed;
2075 }
2076
2077 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2078 if (!cmd) {
2079 err = -ENOMEM;
2080 goto failed;
2081 }
2082
2083 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2084 if (err < 0) {
2085 mgmt_pending_remove(cmd);
2086 goto failed;
2087 }
2088
2089failed:
2090 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002091 return err;
2092}
2093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002094static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002095{
2096 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002097 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002098 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002099 int err;
2100
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002101 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002102
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002103 status = mgmt_bredr_support(hdev);
2104 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002105 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002106
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002107 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002108 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2109 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002110
Johan Hedberga7e80f22013-01-09 16:05:19 +02002111 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002112 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2113 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002114
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002115 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002116
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002117 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002118 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002119
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002120 if (cp->val) {
2121 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2122 &hdev->dev_flags);
2123 } else {
2124 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2125 &hdev->dev_flags);
2126 if (!changed)
2127 changed = test_and_clear_bit(HCI_HS_ENABLED,
2128 &hdev->dev_flags);
2129 else
2130 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002131 }
2132
2133 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2134 if (err < 0)
2135 goto failed;
2136
2137 if (changed)
2138 err = new_settings(hdev, sk);
2139
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002140 goto failed;
2141 }
2142
Johan Hedberg94d52da2015-02-19 17:38:06 +02002143 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002144 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2145 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002146 goto failed;
2147 }
2148
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002149 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002150 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2151 goto failed;
2152 }
2153
2154 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2155 if (!cmd) {
2156 err = -ENOMEM;
2157 goto failed;
2158 }
2159
Johan Hedberg37699722014-06-24 14:00:27 +03002160 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2161 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2162 sizeof(cp->val), &cp->val);
2163
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002164 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002165 if (err < 0) {
2166 mgmt_pending_remove(cmd);
2167 goto failed;
2168 }
2169
2170failed:
2171 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002172 return err;
2173}
2174
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002175static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002176{
2177 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002178 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002179 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002180 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002181
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002182 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002183
Johan Hedberge6fe7982013-10-02 15:45:22 +03002184 status = mgmt_bredr_support(hdev);
2185 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002186 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002187
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002188 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002189 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2190 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002191
2192 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002193 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2194 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002195
Johan Hedberga7e80f22013-01-09 16:05:19 +02002196 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002197 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2198 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002199
Marcel Holtmannee392692013-10-01 22:59:23 -07002200 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002201
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002202 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002203 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2204 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002205 goto unlock;
2206 }
2207
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002208 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002209 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002210 } else {
2211 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002212 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2213 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002214 goto unlock;
2215 }
2216
Marcel Holtmannee392692013-10-01 22:59:23 -07002217 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002218 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002219
2220 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2221 if (err < 0)
2222 goto unlock;
2223
2224 if (changed)
2225 err = new_settings(hdev, sk);
2226
2227unlock:
2228 hci_dev_unlock(hdev);
2229 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002230}
2231
Marcel Holtmann1904a852015-01-11 13:50:44 -08002232static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002233{
2234 struct cmd_lookup match = { NULL, hdev };
2235
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302236 hci_dev_lock(hdev);
2237
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002238 if (status) {
2239 u8 mgmt_err = mgmt_status(status);
2240
2241 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2242 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302243 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002244 }
2245
2246 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2247
2248 new_settings(hdev, match.sk);
2249
2250 if (match.sk)
2251 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002252
2253 /* Make sure the controller has a good default for
2254 * advertising data. Restrict the update to when LE
2255 * has actually been enabled. During power on, the
2256 * update in powered_update_hci will take care of it.
2257 */
2258 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2259 struct hci_request req;
2260
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002261 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002262 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002263 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002264 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002265 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002266 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302267
2268unlock:
2269 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002270}
2271
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002272static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002273{
2274 struct mgmt_mode *cp = data;
2275 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002276 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002277 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002278 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002279 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002280
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002281 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002282
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002283 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002284 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2285 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002286
Johan Hedberga7e80f22013-01-09 16:05:19 +02002287 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002288 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2289 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002290
Johan Hedbergc73eee92013-04-19 18:35:21 +03002291 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002292 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002293 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2294 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002295
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002296 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002297
2298 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002299 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002300
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002301 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002302 bool changed = false;
2303
2304 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2305 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2306 changed = true;
2307 }
2308
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002309 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2310 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002311 changed = true;
2312 }
2313
Johan Hedberg06199cf2012-02-22 16:37:11 +02002314 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2315 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002316 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002317
2318 if (changed)
2319 err = new_settings(hdev, sk);
2320
Johan Hedberg1de028c2012-02-29 19:55:35 -08002321 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002322 }
2323
Johan Hedberg4375f102013-09-25 13:26:10 +03002324 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2325 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002326 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2327 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002328 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002329 }
2330
2331 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2332 if (!cmd) {
2333 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002334 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002335 }
2336
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002337 hci_req_init(&req, hdev);
2338
Johan Hedberg06199cf2012-02-22 16:37:11 +02002339 memset(&hci_cp, 0, sizeof(hci_cp));
2340
2341 if (val) {
2342 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002343 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002344 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002345 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002346 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002347 }
2348
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002349 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2350 &hci_cp);
2351
2352 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302353 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002354 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002355
Johan Hedberg1de028c2012-02-29 19:55:35 -08002356unlock:
2357 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002358 return err;
2359}
2360
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002361/* This is a helper function to test for pending mgmt commands that can
2362 * cause CoD or EIR HCI commands. We can only allow one such pending
2363 * mgmt command at a time since otherwise we cannot easily track what
2364 * the current values are, will be, and based on that calculate if a new
2365 * HCI command needs to be sent and if yes with what value.
2366 */
2367static bool pending_eir_or_class(struct hci_dev *hdev)
2368{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002369 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002370
2371 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2372 switch (cmd->opcode) {
2373 case MGMT_OP_ADD_UUID:
2374 case MGMT_OP_REMOVE_UUID:
2375 case MGMT_OP_SET_DEV_CLASS:
2376 case MGMT_OP_SET_POWERED:
2377 return true;
2378 }
2379 }
2380
2381 return false;
2382}
2383
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002384static const u8 bluetooth_base_uuid[] = {
2385 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2386 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2387};
2388
2389static u8 get_uuid_size(const u8 *uuid)
2390{
2391 u32 val;
2392
2393 if (memcmp(uuid, bluetooth_base_uuid, 12))
2394 return 128;
2395
2396 val = get_unaligned_le32(&uuid[12]);
2397 if (val > 0xffff)
2398 return 32;
2399
2400 return 16;
2401}
2402
Johan Hedberg92da6092013-03-15 17:06:55 -05002403static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2404{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002405 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002406
2407 hci_dev_lock(hdev);
2408
2409 cmd = mgmt_pending_find(mgmt_op, hdev);
2410 if (!cmd)
2411 goto unlock;
2412
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002413 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2414 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002415
2416 mgmt_pending_remove(cmd);
2417
2418unlock:
2419 hci_dev_unlock(hdev);
2420}
2421
Marcel Holtmann1904a852015-01-11 13:50:44 -08002422static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002423{
2424 BT_DBG("status 0x%02x", status);
2425
2426 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2427}
2428
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002429static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002430{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002431 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002432 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002433 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002434 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002435 int err;
2436
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002437 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002438
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002439 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002440
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002441 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002442 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2443 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002444 goto failed;
2445 }
2446
Andre Guedes92c4c202012-06-07 19:05:44 -03002447 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002448 if (!uuid) {
2449 err = -ENOMEM;
2450 goto failed;
2451 }
2452
2453 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002454 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002455 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002456
Johan Hedbergde66aa62013-01-27 00:31:27 +02002457 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002458
Johan Hedberg890ea892013-03-15 17:06:52 -05002459 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002460
Johan Hedberg890ea892013-03-15 17:06:52 -05002461 update_class(&req);
2462 update_eir(&req);
2463
Johan Hedberg92da6092013-03-15 17:06:55 -05002464 err = hci_req_run(&req, add_uuid_complete);
2465 if (err < 0) {
2466 if (err != -ENODATA)
2467 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002468
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002469 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2470 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002471 goto failed;
2472 }
2473
2474 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002475 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002476 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002477 goto failed;
2478 }
2479
2480 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481
2482failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002483 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002484 return err;
2485}
2486
Johan Hedberg24b78d02012-02-23 23:24:30 +02002487static bool enable_service_cache(struct hci_dev *hdev)
2488{
2489 if (!hdev_is_powered(hdev))
2490 return false;
2491
2492 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002493 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2494 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002495 return true;
2496 }
2497
2498 return false;
2499}
2500
Marcel Holtmann1904a852015-01-11 13:50:44 -08002501static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002502{
2503 BT_DBG("status 0x%02x", status);
2504
2505 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2506}
2507
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002508static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002509 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002510{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002511 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002512 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002513 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 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 -05002515 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002516 int err, found;
2517
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002518 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002519
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002520 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002521
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002522 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002523 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2524 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002525 goto unlock;
2526 }
2527
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002528 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002529 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002530
Johan Hedberg24b78d02012-02-23 23:24:30 +02002531 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002532 err = mgmt_cmd_complete(sk, hdev->id,
2533 MGMT_OP_REMOVE_UUID,
2534 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002535 goto unlock;
2536 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002537
Johan Hedberg9246a862012-02-23 21:33:16 +02002538 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002539 }
2540
2541 found = 0;
2542
Johan Hedberg056341c2013-01-27 00:31:30 +02002543 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002544 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2545 continue;
2546
2547 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002548 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002549 found++;
2550 }
2551
2552 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002553 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2554 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002555 goto unlock;
2556 }
2557
Johan Hedberg9246a862012-02-23 21:33:16 +02002558update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002559 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002560
Johan Hedberg890ea892013-03-15 17:06:52 -05002561 update_class(&req);
2562 update_eir(&req);
2563
Johan Hedberg92da6092013-03-15 17:06:55 -05002564 err = hci_req_run(&req, remove_uuid_complete);
2565 if (err < 0) {
2566 if (err != -ENODATA)
2567 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002568
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002569 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2570 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002571 goto unlock;
2572 }
2573
2574 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002575 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002576 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002577 goto unlock;
2578 }
2579
2580 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002581
2582unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002583 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002584 return err;
2585}
2586
Marcel Holtmann1904a852015-01-11 13:50:44 -08002587static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002588{
2589 BT_DBG("status 0x%02x", status);
2590
2591 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2592}
2593
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002594static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002595 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002596{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002597 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002598 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002599 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002600 int err;
2601
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002602 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002603
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002604 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002605 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2606 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002607
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002608 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002609
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002610 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002611 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2612 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002613 goto unlock;
2614 }
2615
2616 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002617 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2618 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002619 goto unlock;
2620 }
2621
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002622 hdev->major_class = cp->major;
2623 hdev->minor_class = cp->minor;
2624
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002625 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002626 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2627 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002628 goto unlock;
2629 }
2630
Johan Hedberg890ea892013-03-15 17:06:52 -05002631 hci_req_init(&req, hdev);
2632
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002633 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002634 hci_dev_unlock(hdev);
2635 cancel_delayed_work_sync(&hdev->service_cache);
2636 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002637 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002638 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002639
Johan Hedberg890ea892013-03-15 17:06:52 -05002640 update_class(&req);
2641
Johan Hedberg92da6092013-03-15 17:06:55 -05002642 err = hci_req_run(&req, set_class_complete);
2643 if (err < 0) {
2644 if (err != -ENODATA)
2645 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002646
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002647 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2648 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002649 goto unlock;
2650 }
2651
2652 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002653 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002654 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002655 goto unlock;
2656 }
2657
2658 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002659
Johan Hedbergb5235a62012-02-21 14:32:24 +02002660unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002661 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002662 return err;
2663}
2664
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002665static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002666 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002667{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002668 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002669 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2670 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002671 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002672 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002673 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002674
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002675 BT_DBG("request for %s", hdev->name);
2676
2677 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002678 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2679 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002680
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002681 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002682 if (key_count > max_key_count) {
2683 BT_ERR("load_link_keys: too big key_count value %u",
2684 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002685 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2686 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002687 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002688
Johan Hedberg86742e12011-11-07 23:13:38 +02002689 expected_len = sizeof(*cp) + key_count *
2690 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002691 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002692 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002693 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002694 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2695 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002696 }
2697
Johan Hedberg4ae14302013-01-20 14:27:13 +02002698 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002699 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2700 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002701
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002702 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002703 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002704
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002705 for (i = 0; i < key_count; i++) {
2706 struct mgmt_link_key_info *key = &cp->keys[i];
2707
Marcel Holtmann8e991132014-01-10 02:07:25 -08002708 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002709 return mgmt_cmd_status(sk, hdev->id,
2710 MGMT_OP_LOAD_LINK_KEYS,
2711 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002712 }
2713
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002714 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002715
2716 hci_link_keys_clear(hdev);
2717
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002718 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002719 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2720 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002721 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002722 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2723 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002724
2725 if (changed)
2726 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002727
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002728 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002729 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002730
Johan Hedberg58e92932014-06-24 14:00:26 +03002731 /* Always ignore debug keys and require a new pairing if
2732 * the user wants to use them.
2733 */
2734 if (key->type == HCI_LK_DEBUG_COMBINATION)
2735 continue;
2736
Johan Hedberg7652ff62014-06-24 13:15:49 +03002737 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2738 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002739 }
2740
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002741 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002742
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002743 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002744
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002745 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002746}
2747
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002748static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002749 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002750{
2751 struct mgmt_ev_device_unpaired ev;
2752
2753 bacpy(&ev.addr.bdaddr, bdaddr);
2754 ev.addr.type = addr_type;
2755
2756 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002757 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002758}
2759
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002760static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002761 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002762{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002763 struct mgmt_cp_unpair_device *cp = data;
2764 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002765 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002766 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002767 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002768 int err;
2769
Johan Hedberga8a1d192011-11-10 15:54:38 +02002770 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002771 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2772 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002773
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002774 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002775 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2776 MGMT_STATUS_INVALID_PARAMS,
2777 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002778
Johan Hedberg118da702013-01-20 14:27:20 +02002779 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002780 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2781 MGMT_STATUS_INVALID_PARAMS,
2782 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002783
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002784 hci_dev_lock(hdev);
2785
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002786 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002787 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2788 MGMT_STATUS_NOT_POWERED, &rp,
2789 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002790 goto unlock;
2791 }
2792
Johan Hedberge0b2b272014-02-18 17:14:31 +02002793 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002794 /* If disconnection is requested, then look up the
2795 * connection. If the remote device is connected, it
2796 * will be later used to terminate the link.
2797 *
2798 * Setting it to NULL explicitly will cause no
2799 * termination of the link.
2800 */
2801 if (cp->disconnect)
2802 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2803 &cp->addr.bdaddr);
2804 else
2805 conn = NULL;
2806
Johan Hedberg124f6e32012-02-09 13:50:12 +02002807 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002808 } else {
2809 u8 addr_type;
2810
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002811 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2812 &cp->addr.bdaddr);
2813 if (conn) {
2814 /* Defer clearing up the connection parameters
2815 * until closing to give a chance of keeping
2816 * them if a repairing happens.
2817 */
2818 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2819
2820 /* If disconnection is not requested, then
2821 * clear the connection variable so that the
2822 * link is not terminated.
2823 */
2824 if (!cp->disconnect)
2825 conn = NULL;
2826 }
2827
Johan Hedberge0b2b272014-02-18 17:14:31 +02002828 if (cp->addr.type == BDADDR_LE_PUBLIC)
2829 addr_type = ADDR_LE_DEV_PUBLIC;
2830 else
2831 addr_type = ADDR_LE_DEV_RANDOM;
2832
Johan Hedberga7ec7332014-02-18 17:14:35 +02002833 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2834
Johan Hedberge0b2b272014-02-18 17:14:31 +02002835 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2836 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002837
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002838 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002839 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2840 MGMT_STATUS_NOT_PAIRED, &rp,
2841 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002842 goto unlock;
2843 }
2844
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002845 /* If the connection variable is set, then termination of the
2846 * link is requested.
2847 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002848 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002849 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2850 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002851 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002852 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002853 }
2854
Johan Hedberg124f6e32012-02-09 13:50:12 +02002855 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002856 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002857 if (!cmd) {
2858 err = -ENOMEM;
2859 goto unlock;
2860 }
2861
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002862 cmd->cmd_complete = addr_cmd_complete;
2863
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002864 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002865 dc.reason = 0x13; /* Remote User Terminated Connection */
2866 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2867 if (err < 0)
2868 mgmt_pending_remove(cmd);
2869
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002870unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002871 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002872 return err;
2873}
2874
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002875static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002876 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002877{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002878 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002879 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002880 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002881 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002882 int err;
2883
2884 BT_DBG("");
2885
Johan Hedberg06a63b12013-01-20 14:27:21 +02002886 memset(&rp, 0, sizeof(rp));
2887 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2888 rp.addr.type = cp->addr.type;
2889
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002890 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002891 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2892 MGMT_STATUS_INVALID_PARAMS,
2893 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002894
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002895 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002896
2897 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002898 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2899 MGMT_STATUS_NOT_POWERED, &rp,
2900 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002901 goto failed;
2902 }
2903
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002904 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002905 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2906 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002907 goto failed;
2908 }
2909
Andre Guedes591f47f2012-04-24 21:02:49 -03002910 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002911 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2912 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002913 else
2914 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002915
Vishal Agarwalf9607272012-06-13 05:32:43 +05302916 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002917 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2918 MGMT_STATUS_NOT_CONNECTED, &rp,
2919 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002920 goto failed;
2921 }
2922
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002923 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002924 if (!cmd) {
2925 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002926 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002927 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002928
Johan Hedbergf5818c22014-12-05 13:36:02 +02002929 cmd->cmd_complete = generic_cmd_complete;
2930
Johan Hedberge3f2f922014-08-18 20:33:33 +03002931 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002932 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002933 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002934
2935failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002936 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002937 return err;
2938}
2939
Andre Guedes57c14772012-04-24 21:02:50 -03002940static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002941{
2942 switch (link_type) {
2943 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002944 switch (addr_type) {
2945 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002946 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002947
Johan Hedberg48264f02011-11-09 13:58:58 +02002948 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002949 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002950 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002951 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002952
Johan Hedberg4c659c32011-11-07 23:13:39 +02002953 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002954 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002955 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002956 }
2957}
2958
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002959static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2960 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002961{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002962 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002963 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002964 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002965 int err;
2966 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002967
2968 BT_DBG("");
2969
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002970 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002971
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002972 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002973 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2974 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002975 goto unlock;
2976 }
2977
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002978 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002979 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2980 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002981 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002982 }
2983
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002984 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002985 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002986 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002987 err = -ENOMEM;
2988 goto unlock;
2989 }
2990
Johan Hedberg2784eb42011-01-21 13:56:35 +02002991 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002992 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002993 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2994 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002995 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002996 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002997 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002998 continue;
2999 i++;
3000 }
3001
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003002 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003003
Johan Hedberg4c659c32011-11-07 23:13:39 +02003004 /* Recalculate length in case of filtered SCO connections, etc */
3005 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003006
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003007 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3008 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003009
Johan Hedberga38528f2011-01-22 06:46:43 +02003010 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003011
3012unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003013 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003014 return err;
3015}
3016
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003017static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003018 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003019{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003020 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003021 int err;
3022
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003023 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003024 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003025 if (!cmd)
3026 return -ENOMEM;
3027
Johan Hedbergd8457692012-02-17 14:24:57 +02003028 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003029 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003030 if (err < 0)
3031 mgmt_pending_remove(cmd);
3032
3033 return err;
3034}
3035
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003036static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003037 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003038{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003039 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003040 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003041 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003042 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003043 int err;
3044
3045 BT_DBG("");
3046
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003047 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003048
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003049 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003050 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3051 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003052 goto failed;
3053 }
3054
Johan Hedbergd8457692012-02-17 14:24:57 +02003055 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003056 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003057 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3058 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003059 goto failed;
3060 }
3061
3062 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003063 struct mgmt_cp_pin_code_neg_reply ncp;
3064
3065 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003066
3067 BT_ERR("PIN code is not 16 bytes long");
3068
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003069 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003070 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003071 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3072 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003073
3074 goto failed;
3075 }
3076
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003077 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003078 if (!cmd) {
3079 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003080 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003081 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003082
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003083 cmd->cmd_complete = addr_cmd_complete;
3084
Johan Hedbergd8457692012-02-17 14:24:57 +02003085 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003086 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003087 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003088
3089 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3090 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003091 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003092
3093failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003094 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003095 return err;
3096}
3097
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003098static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3099 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003100{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003101 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003102
3103 BT_DBG("");
3104
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003105 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003106 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3107 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003108
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003109 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003110
3111 hdev->io_capability = cp->io_capability;
3112
3113 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003114 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003115
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003116 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003117
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003118 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3119 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003120}
3121
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003122static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003123{
3124 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003125 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003126
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003127 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003128 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3129 continue;
3130
Johan Hedberge9a416b2011-02-19 12:05:56 -03003131 if (cmd->user_data != conn)
3132 continue;
3133
3134 return cmd;
3135 }
3136
3137 return NULL;
3138}
3139
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003140static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003141{
3142 struct mgmt_rp_pair_device rp;
3143 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003144 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003145
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003146 bacpy(&rp.addr.bdaddr, &conn->dst);
3147 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003149 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3150 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003151
3152 /* So we don't get further callbacks for this connection */
3153 conn->connect_cfm_cb = NULL;
3154 conn->security_cfm_cb = NULL;
3155 conn->disconn_cfm_cb = NULL;
3156
David Herrmann76a68ba2013-04-06 20:28:37 +02003157 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003158
3159 /* The device is paired so there is no need to remove
3160 * its connection parameters anymore.
3161 */
3162 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003163
3164 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003165
3166 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003167}
3168
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003169void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3170{
3171 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003172 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003173
3174 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003175 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003176 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003177 mgmt_pending_remove(cmd);
3178 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003179}
3180
Johan Hedberge9a416b2011-02-19 12:05:56 -03003181static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3182{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003183 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003184
3185 BT_DBG("status %u", status);
3186
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003187 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003188 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003189 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003190 return;
3191 }
3192
3193 cmd->cmd_complete(cmd, mgmt_status(status));
3194 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003195}
3196
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003197static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303198{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003199 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303200
3201 BT_DBG("status %u", status);
3202
3203 if (!status)
3204 return;
3205
3206 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003207 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303208 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003209 return;
3210 }
3211
3212 cmd->cmd_complete(cmd, mgmt_status(status));
3213 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303214}
3215
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003216static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003217 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003218{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003219 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003220 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003221 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003222 u8 sec_level, auth_type;
3223 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003224 int err;
3225
3226 BT_DBG("");
3227
Szymon Jancf950a30e2013-01-18 12:48:07 +01003228 memset(&rp, 0, sizeof(rp));
3229 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3230 rp.addr.type = cp->addr.type;
3231
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003232 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003233 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3234 MGMT_STATUS_INVALID_PARAMS,
3235 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003236
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003237 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003238 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3239 MGMT_STATUS_INVALID_PARAMS,
3240 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003241
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003242 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003243
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003244 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003245 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3246 MGMT_STATUS_NOT_POWERED, &rp,
3247 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003248 goto unlock;
3249 }
3250
Johan Hedberg55e76b32015-03-10 22:34:40 +02003251 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3252 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3253 MGMT_STATUS_ALREADY_PAIRED, &rp,
3254 sizeof(rp));
3255 goto unlock;
3256 }
3257
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003258 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003259 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003260
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003261 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003262 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3263 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003264 } else {
3265 u8 addr_type;
3266
3267 /* Convert from L2CAP channel address type to HCI address type
3268 */
3269 if (cp->addr.type == BDADDR_LE_PUBLIC)
3270 addr_type = ADDR_LE_DEV_PUBLIC;
3271 else
3272 addr_type = ADDR_LE_DEV_RANDOM;
3273
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003274 /* When pairing a new device, it is expected to remember
3275 * this device for future connections. Adding the connection
3276 * parameter information ahead of time allows tracking
3277 * of the slave preferred values and will speed up any
3278 * further connection establishment.
3279 *
3280 * If connection parameters already exist, then they
3281 * will be kept and this function does nothing.
3282 */
3283 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3284
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003285 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003286 sec_level, HCI_LE_CONN_TIMEOUT,
3287 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003288 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003289
Ville Tervo30e76272011-02-22 16:10:53 -03003290 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003291 int status;
3292
3293 if (PTR_ERR(conn) == -EBUSY)
3294 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003295 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3296 status = MGMT_STATUS_NOT_SUPPORTED;
3297 else if (PTR_ERR(conn) == -ECONNREFUSED)
3298 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003299 else
3300 status = MGMT_STATUS_CONNECT_FAILED;
3301
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003302 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3303 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003304 goto unlock;
3305 }
3306
3307 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003308 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003309 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3310 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003311 goto unlock;
3312 }
3313
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003314 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003315 if (!cmd) {
3316 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003317 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003318 goto unlock;
3319 }
3320
Johan Hedberg04ab2742014-12-05 13:36:04 +02003321 cmd->cmd_complete = pairing_complete;
3322
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003323 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003324 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003325 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003326 conn->security_cfm_cb = pairing_complete_cb;
3327 conn->disconn_cfm_cb = pairing_complete_cb;
3328 } else {
3329 conn->connect_cfm_cb = le_pairing_complete_cb;
3330 conn->security_cfm_cb = le_pairing_complete_cb;
3331 conn->disconn_cfm_cb = le_pairing_complete_cb;
3332 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003333
Johan Hedberge9a416b2011-02-19 12:05:56 -03003334 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003335 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003336
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003337 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003338 hci_conn_security(conn, sec_level, auth_type, true)) {
3339 cmd->cmd_complete(cmd, 0);
3340 mgmt_pending_remove(cmd);
3341 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003342
3343 err = 0;
3344
3345unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003346 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003347 return err;
3348}
3349
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003350static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3351 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003352{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003353 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003354 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003355 struct hci_conn *conn;
3356 int err;
3357
3358 BT_DBG("");
3359
Johan Hedberg28424702012-02-02 04:02:29 +02003360 hci_dev_lock(hdev);
3361
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003362 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003363 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3364 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003365 goto unlock;
3366 }
3367
Johan Hedberg28424702012-02-02 04:02:29 +02003368 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3369 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003370 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3371 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003372 goto unlock;
3373 }
3374
3375 conn = cmd->user_data;
3376
3377 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003378 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3379 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003380 goto unlock;
3381 }
3382
Johan Hedberga511b352014-12-11 21:45:45 +02003383 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3384 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003385
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003386 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3387 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003388unlock:
3389 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003390 return err;
3391}
3392
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003393static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003394 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003395 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003396{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003397 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003398 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003399 int err;
3400
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003401 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003402
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003403 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003404 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3405 MGMT_STATUS_NOT_POWERED, addr,
3406 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003407 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003408 }
3409
Johan Hedberg1707c602013-03-15 17:07:15 -05003410 if (addr->type == BDADDR_BREDR)
3411 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003412 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003413 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003414
Johan Hedberg272d90d2012-02-09 15:26:12 +02003415 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003416 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3417 MGMT_STATUS_NOT_CONNECTED, addr,
3418 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003419 goto done;
3420 }
3421
Johan Hedberg1707c602013-03-15 17:07:15 -05003422 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003423 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003424 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003425 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3426 MGMT_STATUS_SUCCESS, addr,
3427 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003428 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003429 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3430 MGMT_STATUS_FAILED, addr,
3431 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003432
Brian Gix47c15e22011-11-16 13:53:14 -08003433 goto done;
3434 }
3435
Johan Hedberg1707c602013-03-15 17:07:15 -05003436 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003437 if (!cmd) {
3438 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003439 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003440 }
3441
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003442 cmd->cmd_complete = addr_cmd_complete;
3443
Brian Gix0df4c182011-11-16 13:53:13 -08003444 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003445 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3446 struct hci_cp_user_passkey_reply cp;
3447
Johan Hedberg1707c602013-03-15 17:07:15 -05003448 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003449 cp.passkey = passkey;
3450 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3451 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003452 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3453 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003454
Johan Hedberga664b5b2011-02-19 12:06:02 -03003455 if (err < 0)
3456 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003457
Brian Gix0df4c182011-11-16 13:53:13 -08003458done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003459 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003460 return err;
3461}
3462
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303463static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3464 void *data, u16 len)
3465{
3466 struct mgmt_cp_pin_code_neg_reply *cp = data;
3467
3468 BT_DBG("");
3469
Johan Hedberg1707c602013-03-15 17:07:15 -05003470 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303471 MGMT_OP_PIN_CODE_NEG_REPLY,
3472 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3473}
3474
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003475static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3476 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003477{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003478 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003479
3480 BT_DBG("");
3481
3482 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003483 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3484 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003485
Johan Hedberg1707c602013-03-15 17:07:15 -05003486 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003487 MGMT_OP_USER_CONFIRM_REPLY,
3488 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003489}
3490
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003491static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003492 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003493{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003494 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003495
3496 BT_DBG("");
3497
Johan Hedberg1707c602013-03-15 17:07:15 -05003498 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003499 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3500 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003501}
3502
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003503static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3504 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003505{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003506 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003507
3508 BT_DBG("");
3509
Johan Hedberg1707c602013-03-15 17:07:15 -05003510 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003511 MGMT_OP_USER_PASSKEY_REPLY,
3512 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003513}
3514
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003515static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003516 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003517{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003518 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003519
3520 BT_DBG("");
3521
Johan Hedberg1707c602013-03-15 17:07:15 -05003522 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003523 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3524 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003525}
3526
Johan Hedberg13928972013-03-15 17:07:00 -05003527static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003528{
Johan Hedberg13928972013-03-15 17:07:00 -05003529 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003530 struct hci_cp_write_local_name cp;
3531
Johan Hedberg13928972013-03-15 17:07:00 -05003532 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003533
Johan Hedberg890ea892013-03-15 17:06:52 -05003534 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003535}
3536
Marcel Holtmann1904a852015-01-11 13:50:44 -08003537static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003538{
3539 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003540 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003541
3542 BT_DBG("status 0x%02x", status);
3543
3544 hci_dev_lock(hdev);
3545
3546 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3547 if (!cmd)
3548 goto unlock;
3549
3550 cp = cmd->param;
3551
3552 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003553 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3554 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003555 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003556 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3557 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003558
3559 mgmt_pending_remove(cmd);
3560
3561unlock:
3562 hci_dev_unlock(hdev);
3563}
3564
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003565static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003566 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003567{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003568 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003569 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003570 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003571 int err;
3572
3573 BT_DBG("");
3574
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003575 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003576
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003577 /* If the old values are the same as the new ones just return a
3578 * direct command complete event.
3579 */
3580 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3581 !memcmp(hdev->short_name, cp->short_name,
3582 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003583 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3584 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003585 goto failed;
3586 }
3587
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003588 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003589
Johan Hedbergb5235a62012-02-21 14:32:24 +02003590 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003591 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003592
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003593 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3594 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003595 if (err < 0)
3596 goto failed;
3597
3598 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003599 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003600
Johan Hedbergb5235a62012-02-21 14:32:24 +02003601 goto failed;
3602 }
3603
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003604 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003605 if (!cmd) {
3606 err = -ENOMEM;
3607 goto failed;
3608 }
3609
Johan Hedberg13928972013-03-15 17:07:00 -05003610 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3611
Johan Hedberg890ea892013-03-15 17:06:52 -05003612 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003613
3614 if (lmp_bredr_capable(hdev)) {
3615 update_name(&req);
3616 update_eir(&req);
3617 }
3618
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003619 /* The name is stored in the scan response data and so
3620 * no need to udpate the advertising data here.
3621 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003622 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003623 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003624
Johan Hedberg13928972013-03-15 17:07:00 -05003625 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003626 if (err < 0)
3627 mgmt_pending_remove(cmd);
3628
3629failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003630 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003631 return err;
3632}
3633
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003634static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003635 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003636{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003637 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003638 int err;
3639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003640 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003641
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003642 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003643
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003644 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003645 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3646 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003647 goto unlock;
3648 }
3649
Andre Guedes9a1a1992012-07-24 15:03:48 -03003650 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003651 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3652 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003653 goto unlock;
3654 }
3655
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003656 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003657 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3658 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003659 goto unlock;
3660 }
3661
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003662 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003663 if (!cmd) {
3664 err = -ENOMEM;
3665 goto unlock;
3666 }
3667
Johan Hedberg710f11c2014-05-26 11:21:22 +03003668 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003669 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3670 0, NULL);
3671 else
3672 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3673
Szymon Jancc35938b2011-03-22 13:12:21 +01003674 if (err < 0)
3675 mgmt_pending_remove(cmd);
3676
3677unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003678 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003679 return err;
3680}
3681
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003682static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003683 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003684{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003685 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003686 int err;
3687
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003688 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003689
Johan Hedberg5d57e792015-01-23 10:10:38 +02003690 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003691 return mgmt_cmd_complete(sk, hdev->id,
3692 MGMT_OP_ADD_REMOTE_OOB_DATA,
3693 MGMT_STATUS_INVALID_PARAMS,
3694 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003695
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003696 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003697
Marcel Holtmannec109112014-01-10 02:07:30 -08003698 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3699 struct mgmt_cp_add_remote_oob_data *cp = data;
3700 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003701
Johan Hedbergc19a4952014-11-17 20:52:19 +02003702 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003703 err = mgmt_cmd_complete(sk, hdev->id,
3704 MGMT_OP_ADD_REMOTE_OOB_DATA,
3705 MGMT_STATUS_INVALID_PARAMS,
3706 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003707 goto unlock;
3708 }
3709
Marcel Holtmannec109112014-01-10 02:07:30 -08003710 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003711 cp->addr.type, cp->hash,
3712 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003713 if (err < 0)
3714 status = MGMT_STATUS_FAILED;
3715 else
3716 status = MGMT_STATUS_SUCCESS;
3717
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003718 err = mgmt_cmd_complete(sk, hdev->id,
3719 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3720 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003721 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3722 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003723 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003724 u8 status;
3725
Johan Hedberg86df9202014-10-26 20:52:27 +01003726 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003727 /* Enforce zero-valued 192-bit parameters as
3728 * long as legacy SMP OOB isn't implemented.
3729 */
3730 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3731 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003732 err = mgmt_cmd_complete(sk, hdev->id,
3733 MGMT_OP_ADD_REMOTE_OOB_DATA,
3734 MGMT_STATUS_INVALID_PARAMS,
3735 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003736 goto unlock;
3737 }
3738
Johan Hedberg86df9202014-10-26 20:52:27 +01003739 rand192 = NULL;
3740 hash192 = NULL;
3741 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003742 /* In case one of the P-192 values is set to zero,
3743 * then just disable OOB data for P-192.
3744 */
3745 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3746 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3747 rand192 = NULL;
3748 hash192 = NULL;
3749 } else {
3750 rand192 = cp->rand192;
3751 hash192 = cp->hash192;
3752 }
3753 }
3754
3755 /* In case one of the P-256 values is set to zero, then just
3756 * disable OOB data for P-256.
3757 */
3758 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3759 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3760 rand256 = NULL;
3761 hash256 = NULL;
3762 } else {
3763 rand256 = cp->rand256;
3764 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003765 }
3766
Johan Hedberg81328d52014-10-26 20:33:47 +01003767 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003768 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003769 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003770 if (err < 0)
3771 status = MGMT_STATUS_FAILED;
3772 else
3773 status = MGMT_STATUS_SUCCESS;
3774
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003775 err = mgmt_cmd_complete(sk, hdev->id,
3776 MGMT_OP_ADD_REMOTE_OOB_DATA,
3777 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003778 } else {
3779 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003780 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3781 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003782 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003783
Johan Hedbergc19a4952014-11-17 20:52:19 +02003784unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003785 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003786 return err;
3787}
3788
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003789static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003790 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003791{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003792 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003793 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003794 int err;
3795
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003796 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003797
Johan Hedbergc19a4952014-11-17 20:52:19 +02003798 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003799 return mgmt_cmd_complete(sk, hdev->id,
3800 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3801 MGMT_STATUS_INVALID_PARAMS,
3802 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003803
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003804 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003805
Johan Hedbergeedbd582014-11-15 09:34:23 +02003806 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3807 hci_remote_oob_data_clear(hdev);
3808 status = MGMT_STATUS_SUCCESS;
3809 goto done;
3810 }
3811
Johan Hedberg6928a922014-10-26 20:46:09 +01003812 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003813 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003814 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003815 else
Szymon Janca6785be2012-12-13 15:11:21 +01003816 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003817
Johan Hedbergeedbd582014-11-15 09:34:23 +02003818done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003819 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3820 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003821
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003822 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003823 return err;
3824}
3825
Marcel Holtmann80190442014-12-04 11:36:36 +01003826static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003827{
Marcel Holtmann80190442014-12-04 11:36:36 +01003828 struct hci_dev *hdev = req->hdev;
3829 struct hci_cp_le_set_scan_param param_cp;
3830 struct hci_cp_le_set_scan_enable enable_cp;
3831 struct hci_cp_inquiry inq_cp;
3832 /* General inquiry access code (GIAC) */
3833 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3834 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003835 int err;
3836
Marcel Holtmann80190442014-12-04 11:36:36 +01003837 switch (hdev->discovery.type) {
3838 case DISCOV_TYPE_BREDR:
3839 *status = mgmt_bredr_support(hdev);
3840 if (*status)
3841 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003842
Marcel Holtmann80190442014-12-04 11:36:36 +01003843 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3844 *status = MGMT_STATUS_BUSY;
3845 return false;
3846 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003847
Marcel Holtmann80190442014-12-04 11:36:36 +01003848 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003849
Marcel Holtmann80190442014-12-04 11:36:36 +01003850 memset(&inq_cp, 0, sizeof(inq_cp));
3851 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3852 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3853 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3854 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003855
Marcel Holtmann80190442014-12-04 11:36:36 +01003856 case DISCOV_TYPE_LE:
3857 case DISCOV_TYPE_INTERLEAVED:
3858 *status = mgmt_le_support(hdev);
3859 if (*status)
3860 return false;
3861
3862 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3863 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3864 *status = MGMT_STATUS_NOT_SUPPORTED;
3865 return false;
3866 }
3867
3868 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3869 /* Don't let discovery abort an outgoing
3870 * connection attempt that's using directed
3871 * advertising.
3872 */
3873 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3874 BT_CONNECT)) {
3875 *status = MGMT_STATUS_REJECTED;
3876 return false;
3877 }
3878
3879 disable_advertising(req);
3880 }
3881
3882 /* If controller is scanning, it means the background scanning
3883 * is running. Thus, we should temporarily stop it in order to
3884 * set the discovery scanning parameters.
3885 */
3886 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3887 hci_req_add_le_scan_disable(req);
3888
3889 memset(&param_cp, 0, sizeof(param_cp));
3890
3891 /* All active scans will be done with either a resolvable
3892 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003893 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003894 */
3895 err = hci_update_random_address(req, true, &own_addr_type);
3896 if (err < 0) {
3897 *status = MGMT_STATUS_FAILED;
3898 return false;
3899 }
3900
3901 param_cp.type = LE_SCAN_ACTIVE;
3902 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3903 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3904 param_cp.own_address_type = own_addr_type;
3905 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3906 &param_cp);
3907
3908 memset(&enable_cp, 0, sizeof(enable_cp));
3909 enable_cp.enable = LE_SCAN_ENABLE;
3910 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3911 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3912 &enable_cp);
3913 break;
3914
3915 default:
3916 *status = MGMT_STATUS_INVALID_PARAMS;
3917 return false;
3918 }
3919
3920 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003921}
3922
Marcel Holtmann1904a852015-01-11 13:50:44 -08003923static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3924 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003925{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003926 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003927 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003928
Andre Guedes7c307722013-04-30 15:29:28 -03003929 BT_DBG("status %d", status);
3930
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003931 hci_dev_lock(hdev);
3932
3933 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003934 if (!cmd)
3935 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3936
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003937 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003938 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003939 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003940 }
3941
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003942 if (status) {
3943 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3944 goto unlock;
3945 }
3946
Andre Guedes7c307722013-04-30 15:29:28 -03003947 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003948
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003949 /* If the scan involves LE scan, pick proper timeout to schedule
3950 * hdev->le_scan_disable that will stop it.
3951 */
Andre Guedes7c307722013-04-30 15:29:28 -03003952 switch (hdev->discovery.type) {
3953 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003954 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003955 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003956 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003957 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003958 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003959 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003960 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003961 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003962 default:
3963 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003964 timeout = 0;
3965 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003966 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003967
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003968 if (timeout) {
3969 /* When service discovery is used and the controller has
3970 * a strict duplicate filter, it is important to remember
3971 * the start and duration of the scan. This is required
3972 * for restarting scanning during the discovery phase.
3973 */
3974 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3975 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003976 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003977 hdev->discovery.scan_start = jiffies;
3978 hdev->discovery.scan_duration = timeout;
3979 }
3980
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003981 queue_delayed_work(hdev->workqueue,
3982 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003983 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003984
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003985unlock:
3986 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003987}
3988
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003989static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003990 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003991{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003992 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003993 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003994 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003995 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003996 int err;
3997
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003998 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003999
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004000 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004001
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004002 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004003 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4004 MGMT_STATUS_NOT_POWERED,
4005 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004006 goto failed;
4007 }
4008
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004009 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4010 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004011 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4012 MGMT_STATUS_BUSY, &cp->type,
4013 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004014 goto failed;
4015 }
4016
Johan Hedberg2922a942014-12-05 13:36:06 +02004017 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004018 if (!cmd) {
4019 err = -ENOMEM;
4020 goto failed;
4021 }
4022
Johan Hedberg2922a942014-12-05 13:36:06 +02004023 cmd->cmd_complete = generic_cmd_complete;
4024
Marcel Holtmann22078802014-12-05 11:45:22 +01004025 /* Clear the discovery filter first to free any previously
4026 * allocated memory for the UUID list.
4027 */
4028 hci_discovery_filter_clear(hdev);
4029
Andre Guedes4aab14e2012-02-17 20:39:36 -03004030 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004031 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004032
Andre Guedes7c307722013-04-30 15:29:28 -03004033 hci_req_init(&req, hdev);
4034
Marcel Holtmann80190442014-12-04 11:36:36 +01004035 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004036 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4037 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004038 mgmt_pending_remove(cmd);
4039 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004040 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004041
Andre Guedes7c307722013-04-30 15:29:28 -03004042 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004043 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004044 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004045 goto failed;
4046 }
4047
4048 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004049
4050failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004051 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004052 return err;
4053}
4054
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004055static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4056 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004057{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004058 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4059 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004060}
4061
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004062static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4063 void *data, u16 len)
4064{
4065 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004066 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004067 struct hci_request req;
4068 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4069 u16 uuid_count, expected_len;
4070 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004071 int err;
4072
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004073 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004074
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004075 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004076
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004077 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004078 err = mgmt_cmd_complete(sk, hdev->id,
4079 MGMT_OP_START_SERVICE_DISCOVERY,
4080 MGMT_STATUS_NOT_POWERED,
4081 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004082 goto failed;
4083 }
4084
4085 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4086 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004087 err = mgmt_cmd_complete(sk, hdev->id,
4088 MGMT_OP_START_SERVICE_DISCOVERY,
4089 MGMT_STATUS_BUSY, &cp->type,
4090 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004091 goto failed;
4092 }
4093
4094 uuid_count = __le16_to_cpu(cp->uuid_count);
4095 if (uuid_count > max_uuid_count) {
4096 BT_ERR("service_discovery: too big uuid_count value %u",
4097 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004098 err = mgmt_cmd_complete(sk, hdev->id,
4099 MGMT_OP_START_SERVICE_DISCOVERY,
4100 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4101 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004102 goto failed;
4103 }
4104
4105 expected_len = sizeof(*cp) + uuid_count * 16;
4106 if (expected_len != len) {
4107 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4108 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004109 err = mgmt_cmd_complete(sk, hdev->id,
4110 MGMT_OP_START_SERVICE_DISCOVERY,
4111 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4112 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004113 goto failed;
4114 }
4115
4116 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004117 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004118 if (!cmd) {
4119 err = -ENOMEM;
4120 goto failed;
4121 }
4122
Johan Hedberg2922a942014-12-05 13:36:06 +02004123 cmd->cmd_complete = service_discovery_cmd_complete;
4124
Marcel Holtmann22078802014-12-05 11:45:22 +01004125 /* Clear the discovery filter first to free any previously
4126 * allocated memory for the UUID list.
4127 */
4128 hci_discovery_filter_clear(hdev);
4129
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004130 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004131 hdev->discovery.type = cp->type;
4132 hdev->discovery.rssi = cp->rssi;
4133 hdev->discovery.uuid_count = uuid_count;
4134
4135 if (uuid_count > 0) {
4136 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4137 GFP_KERNEL);
4138 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004139 err = mgmt_cmd_complete(sk, hdev->id,
4140 MGMT_OP_START_SERVICE_DISCOVERY,
4141 MGMT_STATUS_FAILED,
4142 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004143 mgmt_pending_remove(cmd);
4144 goto failed;
4145 }
4146 }
4147
4148 hci_req_init(&req, hdev);
4149
4150 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004151 err = mgmt_cmd_complete(sk, hdev->id,
4152 MGMT_OP_START_SERVICE_DISCOVERY,
4153 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004154 mgmt_pending_remove(cmd);
4155 goto failed;
4156 }
4157
4158 err = hci_req_run(&req, start_discovery_complete);
4159 if (err < 0) {
4160 mgmt_pending_remove(cmd);
4161 goto failed;
4162 }
4163
4164 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4165
4166failed:
4167 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004168 return err;
4169}
4170
Marcel Holtmann1904a852015-01-11 13:50:44 -08004171static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004172{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004173 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004174
Andre Guedes0e05bba2013-04-30 15:29:33 -03004175 BT_DBG("status %d", status);
4176
4177 hci_dev_lock(hdev);
4178
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004179 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4180 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004181 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004182 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004183 }
4184
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004185 if (!status)
4186 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004187
Andre Guedes0e05bba2013-04-30 15:29:33 -03004188 hci_dev_unlock(hdev);
4189}
4190
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004191static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004192 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004193{
Johan Hedbergd9306502012-02-20 23:25:18 +02004194 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004195 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004196 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004197 int err;
4198
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004199 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004200
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004201 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004202
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004203 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004204 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4205 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4206 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004207 goto unlock;
4208 }
4209
4210 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004211 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4212 MGMT_STATUS_INVALID_PARAMS,
4213 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004214 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004215 }
4216
Johan Hedberg2922a942014-12-05 13:36:06 +02004217 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004218 if (!cmd) {
4219 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004220 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004221 }
4222
Johan Hedberg2922a942014-12-05 13:36:06 +02004223 cmd->cmd_complete = generic_cmd_complete;
4224
Andre Guedes0e05bba2013-04-30 15:29:33 -03004225 hci_req_init(&req, hdev);
4226
Johan Hedberg21a60d32014-06-10 14:05:58 +03004227 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004228
Johan Hedberg21a60d32014-06-10 14:05:58 +03004229 err = hci_req_run(&req, stop_discovery_complete);
4230 if (!err) {
4231 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004232 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004233 }
4234
Johan Hedberg21a60d32014-06-10 14:05:58 +03004235 mgmt_pending_remove(cmd);
4236
4237 /* If no HCI commands were sent we're done */
4238 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004239 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4240 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004241 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4242 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004243
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004244unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004245 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004246 return err;
4247}
4248
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004249static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004250 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004251{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004252 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004253 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004254 int err;
4255
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004256 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004257
Johan Hedberg561aafb2012-01-04 13:31:59 +02004258 hci_dev_lock(hdev);
4259
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004260 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004261 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4262 MGMT_STATUS_FAILED, &cp->addr,
4263 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004264 goto failed;
4265 }
4266
Johan Hedberga198e7b2012-02-17 14:27:06 +02004267 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004268 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004269 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4270 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4271 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004272 goto failed;
4273 }
4274
4275 if (cp->name_known) {
4276 e->name_state = NAME_KNOWN;
4277 list_del(&e->list);
4278 } else {
4279 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004280 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004281 }
4282
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004283 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4284 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004285
4286failed:
4287 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004288 return err;
4289}
4290
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004291static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004292 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004293{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004294 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004295 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004296 int err;
4297
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004298 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004299
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004300 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004301 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4302 MGMT_STATUS_INVALID_PARAMS,
4303 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004304
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004305 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004306
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004307 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4308 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004309 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004310 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004311 goto done;
4312 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004313
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004314 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4315 sk);
4316 status = MGMT_STATUS_SUCCESS;
4317
4318done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004319 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4320 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004321
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004322 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004323
4324 return err;
4325}
4326
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004327static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004328 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004329{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004330 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004331 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004332 int err;
4333
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004334 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004335
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004336 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004337 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4338 MGMT_STATUS_INVALID_PARAMS,
4339 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004340
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004341 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004342
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004343 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4344 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004345 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004346 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004347 goto done;
4348 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004349
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004350 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4351 sk);
4352 status = MGMT_STATUS_SUCCESS;
4353
4354done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004355 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4356 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004357
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004358 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004359
4360 return err;
4361}
4362
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004363static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4364 u16 len)
4365{
4366 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004367 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004368 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004369 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004370
4371 BT_DBG("%s", hdev->name);
4372
Szymon Jancc72d4b82012-03-16 16:02:57 +01004373 source = __le16_to_cpu(cp->source);
4374
4375 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004376 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4377 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004378
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004379 hci_dev_lock(hdev);
4380
Szymon Jancc72d4b82012-03-16 16:02:57 +01004381 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004382 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4383 hdev->devid_product = __le16_to_cpu(cp->product);
4384 hdev->devid_version = __le16_to_cpu(cp->version);
4385
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004386 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4387 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004388
Johan Hedberg890ea892013-03-15 17:06:52 -05004389 hci_req_init(&req, hdev);
4390 update_eir(&req);
4391 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004392
4393 hci_dev_unlock(hdev);
4394
4395 return err;
4396}
4397
Marcel Holtmann1904a852015-01-11 13:50:44 -08004398static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4399 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004400{
4401 struct cmd_lookup match = { NULL, hdev };
4402
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304403 hci_dev_lock(hdev);
4404
Johan Hedberg4375f102013-09-25 13:26:10 +03004405 if (status) {
4406 u8 mgmt_err = mgmt_status(status);
4407
4408 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4409 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304410 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004411 }
4412
Johan Hedbergc93bd152014-07-08 15:07:48 +03004413 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4414 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4415 else
4416 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4417
Johan Hedberg4375f102013-09-25 13:26:10 +03004418 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4419 &match);
4420
4421 new_settings(hdev, match.sk);
4422
4423 if (match.sk)
4424 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304425
4426unlock:
4427 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004428}
4429
Marcel Holtmann21b51872013-10-10 09:47:53 -07004430static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4431 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004432{
4433 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004434 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004435 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004436 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004437 int err;
4438
4439 BT_DBG("request for %s", hdev->name);
4440
Johan Hedberge6fe7982013-10-02 15:45:22 +03004441 status = mgmt_le_support(hdev);
4442 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004443 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4444 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004445
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004446 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004447 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4448 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004449
4450 hci_dev_lock(hdev);
4451
4452 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004453
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004454 /* The following conditions are ones which mean that we should
4455 * not do any HCI communication but directly send a mgmt
4456 * response to user space (after toggling the flag if
4457 * necessary).
4458 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004459 if (!hdev_is_powered(hdev) ||
4460 (val == test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
4461 (cp->val == 0x02) == test_bit(HCI_ADVERTISING_CONNECTABLE,
4462 &hdev->dev_flags)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004463 hci_conn_num(hdev, LE_LINK) > 0 ||
4464 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4465 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004466 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004467
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004468 if (cp->val) {
4469 changed = !test_and_set_bit(HCI_ADVERTISING,
4470 &hdev->dev_flags);
4471 if (cp->val == 0x02)
4472 set_bit(HCI_ADVERTISING_CONNECTABLE,
4473 &hdev->dev_flags);
4474 else
4475 clear_bit(HCI_ADVERTISING_CONNECTABLE,
4476 &hdev->dev_flags);
4477 } else {
4478 changed = test_and_clear_bit(HCI_ADVERTISING,
4479 &hdev->dev_flags);
4480 clear_bit(HCI_ADVERTISING_CONNECTABLE,
4481 &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004482 }
4483
4484 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4485 if (err < 0)
4486 goto unlock;
4487
4488 if (changed)
4489 err = new_settings(hdev, sk);
4490
4491 goto unlock;
4492 }
4493
4494 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4495 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004496 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4497 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004498 goto unlock;
4499 }
4500
4501 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4502 if (!cmd) {
4503 err = -ENOMEM;
4504 goto unlock;
4505 }
4506
4507 hci_req_init(&req, hdev);
4508
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004509 if (cp->val == 0x02)
4510 set_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags);
4511 else
4512 clear_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags);
4513
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004514 if (val)
4515 enable_advertising(&req);
4516 else
4517 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004518
4519 err = hci_req_run(&req, set_advertising_complete);
4520 if (err < 0)
4521 mgmt_pending_remove(cmd);
4522
4523unlock:
4524 hci_dev_unlock(hdev);
4525 return err;
4526}
4527
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004528static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4529 void *data, u16 len)
4530{
4531 struct mgmt_cp_set_static_address *cp = data;
4532 int err;
4533
4534 BT_DBG("%s", hdev->name);
4535
Marcel Holtmann62af4442013-10-02 22:10:32 -07004536 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004537 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4538 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004539
4540 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004541 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4542 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004543
4544 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4545 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004546 return mgmt_cmd_status(sk, hdev->id,
4547 MGMT_OP_SET_STATIC_ADDRESS,
4548 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004549
4550 /* Two most significant bits shall be set */
4551 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004552 return mgmt_cmd_status(sk, hdev->id,
4553 MGMT_OP_SET_STATIC_ADDRESS,
4554 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004555 }
4556
4557 hci_dev_lock(hdev);
4558
4559 bacpy(&hdev->static_addr, &cp->bdaddr);
4560
Marcel Holtmann93690c22015-03-06 10:11:21 -08004561 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4562 if (err < 0)
4563 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004564
Marcel Holtmann93690c22015-03-06 10:11:21 -08004565 err = new_settings(hdev, sk);
4566
4567unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004568 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004569 return err;
4570}
4571
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004572static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4573 void *data, u16 len)
4574{
4575 struct mgmt_cp_set_scan_params *cp = data;
4576 __u16 interval, window;
4577 int err;
4578
4579 BT_DBG("%s", hdev->name);
4580
4581 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004582 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4583 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004584
4585 interval = __le16_to_cpu(cp->interval);
4586
4587 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004588 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4589 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004590
4591 window = __le16_to_cpu(cp->window);
4592
4593 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004594 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4595 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004596
Marcel Holtmann899e1072013-10-14 09:55:32 -07004597 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004598 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4599 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004600
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004601 hci_dev_lock(hdev);
4602
4603 hdev->le_scan_interval = interval;
4604 hdev->le_scan_window = window;
4605
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004606 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4607 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004608
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004609 /* If background scan is running, restart it so new parameters are
4610 * loaded.
4611 */
4612 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4613 hdev->discovery.state == DISCOVERY_STOPPED) {
4614 struct hci_request req;
4615
4616 hci_req_init(&req, hdev);
4617
4618 hci_req_add_le_scan_disable(&req);
4619 hci_req_add_le_passive_scan(&req);
4620
4621 hci_req_run(&req, NULL);
4622 }
4623
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004624 hci_dev_unlock(hdev);
4625
4626 return err;
4627}
4628
Marcel Holtmann1904a852015-01-11 13:50:44 -08004629static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4630 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004631{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004632 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004633
4634 BT_DBG("status 0x%02x", status);
4635
4636 hci_dev_lock(hdev);
4637
4638 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4639 if (!cmd)
4640 goto unlock;
4641
4642 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004643 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4644 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004645 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004646 struct mgmt_mode *cp = cmd->param;
4647
4648 if (cp->val)
4649 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4650 else
4651 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4652
Johan Hedberg33e38b32013-03-15 17:07:05 -05004653 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4654 new_settings(hdev, cmd->sk);
4655 }
4656
4657 mgmt_pending_remove(cmd);
4658
4659unlock:
4660 hci_dev_unlock(hdev);
4661}
4662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004663static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004664 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004665{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004666 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004667 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004668 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004669 int err;
4670
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004671 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004672
Johan Hedberg56f87902013-10-02 13:43:13 +03004673 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4674 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004675 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4676 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004677
Johan Hedberga7e80f22013-01-09 16:05:19 +02004678 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004679 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4680 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004681
Antti Julkuf6422ec2011-06-22 13:11:56 +03004682 hci_dev_lock(hdev);
4683
Johan Hedberg05cbf292013-03-15 17:07:07 -05004684 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004685 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4686 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004687 goto unlock;
4688 }
4689
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004690 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4691 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4692 hdev);
4693 goto unlock;
4694 }
4695
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004696 if (!hdev_is_powered(hdev)) {
4697 change_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4698 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4699 hdev);
4700 new_settings(hdev, sk);
4701 goto unlock;
4702 }
4703
Johan Hedberg33e38b32013-03-15 17:07:05 -05004704 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4705 data, len);
4706 if (!cmd) {
4707 err = -ENOMEM;
4708 goto unlock;
4709 }
4710
4711 hci_req_init(&req, hdev);
4712
Johan Hedberg406d7802013-03-15 17:07:09 -05004713 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004714
4715 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004716 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004717 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4718 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004719 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004720 }
4721
Johan Hedberg33e38b32013-03-15 17:07:05 -05004722unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004723 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004724
Antti Julkuf6422ec2011-06-22 13:11:56 +03004725 return err;
4726}
4727
Marcel Holtmann1904a852015-01-11 13:50:44 -08004728static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004729{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004730 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004731
4732 BT_DBG("status 0x%02x", status);
4733
4734 hci_dev_lock(hdev);
4735
4736 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4737 if (!cmd)
4738 goto unlock;
4739
4740 if (status) {
4741 u8 mgmt_err = mgmt_status(status);
4742
4743 /* We need to restore the flag if related HCI commands
4744 * failed.
4745 */
4746 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4747
Johan Hedberga69e8372015-03-06 21:08:53 +02004748 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004749 } else {
4750 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4751 new_settings(hdev, cmd->sk);
4752 }
4753
4754 mgmt_pending_remove(cmd);
4755
4756unlock:
4757 hci_dev_unlock(hdev);
4758}
4759
4760static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4761{
4762 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004763 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004764 struct hci_request req;
4765 int err;
4766
4767 BT_DBG("request for %s", hdev->name);
4768
4769 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004770 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4771 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004772
4773 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004774 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4775 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004776
4777 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004778 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4779 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004780
4781 hci_dev_lock(hdev);
4782
4783 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4784 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4785 goto unlock;
4786 }
4787
4788 if (!hdev_is_powered(hdev)) {
4789 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004790 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4791 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4792 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4793 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4794 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4795 }
4796
4797 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4798
4799 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4800 if (err < 0)
4801 goto unlock;
4802
4803 err = new_settings(hdev, sk);
4804 goto unlock;
4805 }
4806
4807 /* Reject disabling when powered on */
4808 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004809 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4810 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004811 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004812 } else {
4813 /* When configuring a dual-mode controller to operate
4814 * with LE only and using a static address, then switching
4815 * BR/EDR back on is not allowed.
4816 *
4817 * Dual-mode controllers shall operate with the public
4818 * address as its identity address for BR/EDR and LE. So
4819 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004820 *
4821 * The same restrictions applies when secure connections
4822 * has been enabled. For BR/EDR this is a controller feature
4823 * while for LE it is a host stack feature. This means that
4824 * switching BR/EDR back on when secure connections has been
4825 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004826 */
4827 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004828 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4829 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004830 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4831 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004832 goto unlock;
4833 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004834 }
4835
4836 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004837 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4838 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004839 goto unlock;
4840 }
4841
4842 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4843 if (!cmd) {
4844 err = -ENOMEM;
4845 goto unlock;
4846 }
4847
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004848 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004849 * generates the correct flags.
4850 */
4851 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4852
4853 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004854
Johan Hedberg432df052014-08-01 11:13:31 +03004855 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004856 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004857
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004858 /* Since only the advertising data flags will change, there
4859 * is no need to update the scan response data.
4860 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004861 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004862
Johan Hedberg0663ca22013-10-02 13:43:14 +03004863 err = hci_req_run(&req, set_bredr_complete);
4864 if (err < 0)
4865 mgmt_pending_remove(cmd);
4866
4867unlock:
4868 hci_dev_unlock(hdev);
4869 return err;
4870}
4871
Johan Hedberga1443f52015-01-23 15:42:46 +02004872static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4873{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004874 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004875 struct mgmt_mode *cp;
4876
4877 BT_DBG("%s status %u", hdev->name, status);
4878
4879 hci_dev_lock(hdev);
4880
4881 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4882 if (!cmd)
4883 goto unlock;
4884
4885 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004886 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4887 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004888 goto remove;
4889 }
4890
4891 cp = cmd->param;
4892
4893 switch (cp->val) {
4894 case 0x00:
4895 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4896 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4897 break;
4898 case 0x01:
4899 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4900 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4901 break;
4902 case 0x02:
4903 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4904 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4905 break;
4906 }
4907
4908 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4909 new_settings(hdev, cmd->sk);
4910
4911remove:
4912 mgmt_pending_remove(cmd);
4913unlock:
4914 hci_dev_unlock(hdev);
4915}
4916
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004917static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4918 void *data, u16 len)
4919{
4920 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004921 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004922 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004923 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004924 int err;
4925
4926 BT_DBG("request for %s", hdev->name);
4927
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004928 if (!lmp_sc_capable(hdev) &&
4929 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004930 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4931 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004932
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004933 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004934 lmp_sc_capable(hdev) &&
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004935 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004936 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4937 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004938
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004939 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004940 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004941 MGMT_STATUS_INVALID_PARAMS);
4942
4943 hci_dev_lock(hdev);
4944
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004945 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004946 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004947 bool changed;
4948
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004949 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004950 changed = !test_and_set_bit(HCI_SC_ENABLED,
4951 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004952 if (cp->val == 0x02)
4953 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4954 else
4955 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4956 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004957 changed = test_and_clear_bit(HCI_SC_ENABLED,
4958 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004959 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4960 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004961
4962 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4963 if (err < 0)
4964 goto failed;
4965
4966 if (changed)
4967 err = new_settings(hdev, sk);
4968
4969 goto failed;
4970 }
4971
4972 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004973 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4974 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004975 goto failed;
4976 }
4977
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004978 val = !!cp->val;
4979
4980 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4981 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004982 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4983 goto failed;
4984 }
4985
4986 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4987 if (!cmd) {
4988 err = -ENOMEM;
4989 goto failed;
4990 }
4991
Johan Hedberga1443f52015-01-23 15:42:46 +02004992 hci_req_init(&req, hdev);
4993 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4994 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004995 if (err < 0) {
4996 mgmt_pending_remove(cmd);
4997 goto failed;
4998 }
4999
5000failed:
5001 hci_dev_unlock(hdev);
5002 return err;
5003}
5004
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005005static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5006 void *data, u16 len)
5007{
5008 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005009 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005010 int err;
5011
5012 BT_DBG("request for %s", hdev->name);
5013
Johan Hedbergb97109792014-06-24 14:00:28 +03005014 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005015 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5016 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005017
5018 hci_dev_lock(hdev);
5019
5020 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03005021 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
5022 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005023 else
Johan Hedberg0663b292014-06-24 13:15:50 +03005024 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
5025 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005026
Johan Hedbergb97109792014-06-24 14:00:28 +03005027 if (cp->val == 0x02)
5028 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
5029 &hdev->dev_flags);
5030 else
5031 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
5032 &hdev->dev_flags);
5033
5034 if (hdev_is_powered(hdev) && use_changed &&
5035 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
5036 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5037 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5038 sizeof(mode), &mode);
5039 }
5040
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005041 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5042 if (err < 0)
5043 goto unlock;
5044
5045 if (changed)
5046 err = new_settings(hdev, sk);
5047
5048unlock:
5049 hci_dev_unlock(hdev);
5050 return err;
5051}
5052
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005053static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5054 u16 len)
5055{
5056 struct mgmt_cp_set_privacy *cp = cp_data;
5057 bool changed;
5058 int err;
5059
5060 BT_DBG("request for %s", hdev->name);
5061
5062 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005063 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5064 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005065
5066 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005067 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5068 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005069
5070 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005071 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5072 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005073
5074 hci_dev_lock(hdev);
5075
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005076 /* If user space supports this command it is also expected to
5077 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5078 */
5079 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5080
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005081 if (cp->privacy) {
5082 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5083 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5084 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5085 } else {
5086 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5087 memset(hdev->irk, 0, sizeof(hdev->irk));
5088 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5089 }
5090
5091 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5092 if (err < 0)
5093 goto unlock;
5094
5095 if (changed)
5096 err = new_settings(hdev, sk);
5097
5098unlock:
5099 hci_dev_unlock(hdev);
5100 return err;
5101}
5102
Johan Hedberg41edf162014-02-18 10:19:35 +02005103static bool irk_is_valid(struct mgmt_irk_info *irk)
5104{
5105 switch (irk->addr.type) {
5106 case BDADDR_LE_PUBLIC:
5107 return true;
5108
5109 case BDADDR_LE_RANDOM:
5110 /* Two most significant bits shall be set */
5111 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5112 return false;
5113 return true;
5114 }
5115
5116 return false;
5117}
5118
5119static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5120 u16 len)
5121{
5122 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005123 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5124 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005125 u16 irk_count, expected_len;
5126 int i, err;
5127
5128 BT_DBG("request for %s", hdev->name);
5129
5130 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005131 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5132 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005133
5134 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005135 if (irk_count > max_irk_count) {
5136 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005137 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5138 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005139 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005140
5141 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5142 if (expected_len != len) {
5143 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005144 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005145 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5146 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005147 }
5148
5149 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5150
5151 for (i = 0; i < irk_count; i++) {
5152 struct mgmt_irk_info *key = &cp->irks[i];
5153
5154 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005155 return mgmt_cmd_status(sk, hdev->id,
5156 MGMT_OP_LOAD_IRKS,
5157 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005158 }
5159
5160 hci_dev_lock(hdev);
5161
5162 hci_smp_irks_clear(hdev);
5163
5164 for (i = 0; i < irk_count; i++) {
5165 struct mgmt_irk_info *irk = &cp->irks[i];
5166 u8 addr_type;
5167
5168 if (irk->addr.type == BDADDR_LE_PUBLIC)
5169 addr_type = ADDR_LE_DEV_PUBLIC;
5170 else
5171 addr_type = ADDR_LE_DEV_RANDOM;
5172
5173 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5174 BDADDR_ANY);
5175 }
5176
5177 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5178
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005179 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005180
5181 hci_dev_unlock(hdev);
5182
5183 return err;
5184}
5185
Johan Hedberg3f706b72013-01-20 14:27:16 +02005186static bool ltk_is_valid(struct mgmt_ltk_info *key)
5187{
5188 if (key->master != 0x00 && key->master != 0x01)
5189 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005190
5191 switch (key->addr.type) {
5192 case BDADDR_LE_PUBLIC:
5193 return true;
5194
5195 case BDADDR_LE_RANDOM:
5196 /* Two most significant bits shall be set */
5197 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5198 return false;
5199 return true;
5200 }
5201
5202 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005203}
5204
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005205static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005206 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005207{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005208 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005209 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5210 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005211 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005212 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005213
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005214 BT_DBG("request for %s", hdev->name);
5215
5216 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005217 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5218 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005219
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005220 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005221 if (key_count > max_key_count) {
5222 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005223 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5224 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005225 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005226
5227 expected_len = sizeof(*cp) + key_count *
5228 sizeof(struct mgmt_ltk_info);
5229 if (expected_len != len) {
5230 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005231 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005232 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5233 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005234 }
5235
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005236 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005237
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005238 for (i = 0; i < key_count; i++) {
5239 struct mgmt_ltk_info *key = &cp->keys[i];
5240
Johan Hedberg3f706b72013-01-20 14:27:16 +02005241 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005242 return mgmt_cmd_status(sk, hdev->id,
5243 MGMT_OP_LOAD_LONG_TERM_KEYS,
5244 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005245 }
5246
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005247 hci_dev_lock(hdev);
5248
5249 hci_smp_ltks_clear(hdev);
5250
5251 for (i = 0; i < key_count; i++) {
5252 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005253 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005254
5255 if (key->addr.type == BDADDR_LE_PUBLIC)
5256 addr_type = ADDR_LE_DEV_PUBLIC;
5257 else
5258 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005259
Johan Hedberg61b43352014-05-29 19:36:53 +03005260 switch (key->type) {
5261 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005262 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005263 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005264 break;
5265 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005266 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005267 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005268 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005269 case MGMT_LTK_P256_UNAUTH:
5270 authenticated = 0x00;
5271 type = SMP_LTK_P256;
5272 break;
5273 case MGMT_LTK_P256_AUTH:
5274 authenticated = 0x01;
5275 type = SMP_LTK_P256;
5276 break;
5277 case MGMT_LTK_P256_DEBUG:
5278 authenticated = 0x00;
5279 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005280 default:
5281 continue;
5282 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005283
Johan Hedberg35d70272014-02-19 14:57:47 +02005284 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005285 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005286 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005287 }
5288
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005289 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005290 NULL, 0);
5291
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005292 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005293
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005294 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005295}
5296
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005297static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005298{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005299 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005300 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005301 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005302
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005303 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005304
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005305 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005306 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005307 rp.tx_power = conn->tx_power;
5308 rp.max_tx_power = conn->max_tx_power;
5309 } else {
5310 rp.rssi = HCI_RSSI_INVALID;
5311 rp.tx_power = HCI_TX_POWER_INVALID;
5312 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005313 }
5314
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005315 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5316 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005317
5318 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005319 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005320
5321 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005322}
5323
Marcel Holtmann1904a852015-01-11 13:50:44 -08005324static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5325 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005326{
5327 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005328 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005329 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005330 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005331 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005332
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005333 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005334
5335 hci_dev_lock(hdev);
5336
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005337 /* Commands sent in request are either Read RSSI or Read Transmit Power
5338 * Level so we check which one was last sent to retrieve connection
5339 * handle. Both commands have handle as first parameter so it's safe to
5340 * cast data on the same command struct.
5341 *
5342 * First command sent is always Read RSSI and we fail only if it fails.
5343 * In other case we simply override error to indicate success as we
5344 * already remembered if TX power value is actually valid.
5345 */
5346 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5347 if (!cp) {
5348 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005349 status = MGMT_STATUS_SUCCESS;
5350 } else {
5351 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005352 }
5353
5354 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005355 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005356 goto unlock;
5357 }
5358
5359 handle = __le16_to_cpu(cp->handle);
5360 conn = hci_conn_hash_lookup_handle(hdev, handle);
5361 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005362 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005363 goto unlock;
5364 }
5365
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005366 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5367 if (!cmd)
5368 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005369
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005370 cmd->cmd_complete(cmd, status);
5371 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005372
5373unlock:
5374 hci_dev_unlock(hdev);
5375}
5376
5377static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5378 u16 len)
5379{
5380 struct mgmt_cp_get_conn_info *cp = data;
5381 struct mgmt_rp_get_conn_info rp;
5382 struct hci_conn *conn;
5383 unsigned long conn_info_age;
5384 int err = 0;
5385
5386 BT_DBG("%s", hdev->name);
5387
5388 memset(&rp, 0, sizeof(rp));
5389 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5390 rp.addr.type = cp->addr.type;
5391
5392 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005393 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5394 MGMT_STATUS_INVALID_PARAMS,
5395 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005396
5397 hci_dev_lock(hdev);
5398
5399 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005400 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5401 MGMT_STATUS_NOT_POWERED, &rp,
5402 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005403 goto unlock;
5404 }
5405
5406 if (cp->addr.type == BDADDR_BREDR)
5407 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5408 &cp->addr.bdaddr);
5409 else
5410 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5411
5412 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005413 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5414 MGMT_STATUS_NOT_CONNECTED, &rp,
5415 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005416 goto unlock;
5417 }
5418
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005419 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005420 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5421 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005422 goto unlock;
5423 }
5424
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005425 /* To avoid client trying to guess when to poll again for information we
5426 * calculate conn info age as random value between min/max set in hdev.
5427 */
5428 conn_info_age = hdev->conn_info_min_age +
5429 prandom_u32_max(hdev->conn_info_max_age -
5430 hdev->conn_info_min_age);
5431
5432 /* Query controller to refresh cached values if they are too old or were
5433 * never read.
5434 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005435 if (time_after(jiffies, conn->conn_info_timestamp +
5436 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005437 !conn->conn_info_timestamp) {
5438 struct hci_request req;
5439 struct hci_cp_read_tx_power req_txp_cp;
5440 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005441 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005442
5443 hci_req_init(&req, hdev);
5444 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5445 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5446 &req_rssi_cp);
5447
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005448 /* For LE links TX power does not change thus we don't need to
5449 * query for it once value is known.
5450 */
5451 if (!bdaddr_type_is_le(cp->addr.type) ||
5452 conn->tx_power == HCI_TX_POWER_INVALID) {
5453 req_txp_cp.handle = cpu_to_le16(conn->handle);
5454 req_txp_cp.type = 0x00;
5455 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5456 sizeof(req_txp_cp), &req_txp_cp);
5457 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005458
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005459 /* Max TX power needs to be read only once per connection */
5460 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5461 req_txp_cp.handle = cpu_to_le16(conn->handle);
5462 req_txp_cp.type = 0x01;
5463 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5464 sizeof(req_txp_cp), &req_txp_cp);
5465 }
5466
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005467 err = hci_req_run(&req, conn_info_refresh_complete);
5468 if (err < 0)
5469 goto unlock;
5470
5471 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5472 data, len);
5473 if (!cmd) {
5474 err = -ENOMEM;
5475 goto unlock;
5476 }
5477
5478 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005479 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005480 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005481
5482 conn->conn_info_timestamp = jiffies;
5483 } else {
5484 /* Cache is valid, just reply with values cached in hci_conn */
5485 rp.rssi = conn->rssi;
5486 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005487 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005488
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005489 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5490 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005491 }
5492
5493unlock:
5494 hci_dev_unlock(hdev);
5495 return err;
5496}
5497
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005498static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005499{
5500 struct hci_conn *conn = cmd->user_data;
5501 struct mgmt_rp_get_clock_info rp;
5502 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005503 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005504
5505 memset(&rp, 0, sizeof(rp));
5506 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5507
5508 if (status)
5509 goto complete;
5510
5511 hdev = hci_dev_get(cmd->index);
5512 if (hdev) {
5513 rp.local_clock = cpu_to_le32(hdev->clock);
5514 hci_dev_put(hdev);
5515 }
5516
5517 if (conn) {
5518 rp.piconet_clock = cpu_to_le32(conn->clock);
5519 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5520 }
5521
5522complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005523 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5524 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005525
5526 if (conn) {
5527 hci_conn_drop(conn);
5528 hci_conn_put(conn);
5529 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005530
5531 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005532}
5533
Marcel Holtmann1904a852015-01-11 13:50:44 -08005534static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005535{
Johan Hedberg95868422014-06-28 17:54:07 +03005536 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005537 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005538 struct hci_conn *conn;
5539
5540 BT_DBG("%s status %u", hdev->name, status);
5541
5542 hci_dev_lock(hdev);
5543
5544 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5545 if (!hci_cp)
5546 goto unlock;
5547
5548 if (hci_cp->which) {
5549 u16 handle = __le16_to_cpu(hci_cp->handle);
5550 conn = hci_conn_hash_lookup_handle(hdev, handle);
5551 } else {
5552 conn = NULL;
5553 }
5554
5555 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5556 if (!cmd)
5557 goto unlock;
5558
Johan Hedberg69487372014-12-05 13:36:07 +02005559 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005560 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005561
5562unlock:
5563 hci_dev_unlock(hdev);
5564}
5565
5566static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5567 u16 len)
5568{
5569 struct mgmt_cp_get_clock_info *cp = data;
5570 struct mgmt_rp_get_clock_info rp;
5571 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005572 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005573 struct hci_request req;
5574 struct hci_conn *conn;
5575 int err;
5576
5577 BT_DBG("%s", hdev->name);
5578
5579 memset(&rp, 0, sizeof(rp));
5580 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5581 rp.addr.type = cp->addr.type;
5582
5583 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005584 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5585 MGMT_STATUS_INVALID_PARAMS,
5586 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005587
5588 hci_dev_lock(hdev);
5589
5590 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005591 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5592 MGMT_STATUS_NOT_POWERED, &rp,
5593 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005594 goto unlock;
5595 }
5596
5597 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5598 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5599 &cp->addr.bdaddr);
5600 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005601 err = mgmt_cmd_complete(sk, hdev->id,
5602 MGMT_OP_GET_CLOCK_INFO,
5603 MGMT_STATUS_NOT_CONNECTED,
5604 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005605 goto unlock;
5606 }
5607 } else {
5608 conn = NULL;
5609 }
5610
5611 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5612 if (!cmd) {
5613 err = -ENOMEM;
5614 goto unlock;
5615 }
5616
Johan Hedberg69487372014-12-05 13:36:07 +02005617 cmd->cmd_complete = clock_info_cmd_complete;
5618
Johan Hedberg95868422014-06-28 17:54:07 +03005619 hci_req_init(&req, hdev);
5620
5621 memset(&hci_cp, 0, sizeof(hci_cp));
5622 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5623
5624 if (conn) {
5625 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005626 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005627
5628 hci_cp.handle = cpu_to_le16(conn->handle);
5629 hci_cp.which = 0x01; /* Piconet clock */
5630 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5631 }
5632
5633 err = hci_req_run(&req, get_clock_info_complete);
5634 if (err < 0)
5635 mgmt_pending_remove(cmd);
5636
5637unlock:
5638 hci_dev_unlock(hdev);
5639 return err;
5640}
5641
Johan Hedberg5a154e62014-12-19 22:26:02 +02005642static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5643{
5644 struct hci_conn *conn;
5645
5646 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5647 if (!conn)
5648 return false;
5649
5650 if (conn->dst_type != type)
5651 return false;
5652
5653 if (conn->state != BT_CONNECTED)
5654 return false;
5655
5656 return true;
5657}
5658
5659/* This function requires the caller holds hdev->lock */
5660static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5661 u8 addr_type, u8 auto_connect)
5662{
5663 struct hci_dev *hdev = req->hdev;
5664 struct hci_conn_params *params;
5665
5666 params = hci_conn_params_add(hdev, addr, addr_type);
5667 if (!params)
5668 return -EIO;
5669
5670 if (params->auto_connect == auto_connect)
5671 return 0;
5672
5673 list_del_init(&params->action);
5674
5675 switch (auto_connect) {
5676 case HCI_AUTO_CONN_DISABLED:
5677 case HCI_AUTO_CONN_LINK_LOSS:
5678 __hci_update_background_scan(req);
5679 break;
5680 case HCI_AUTO_CONN_REPORT:
5681 list_add(&params->action, &hdev->pend_le_reports);
5682 __hci_update_background_scan(req);
5683 break;
5684 case HCI_AUTO_CONN_DIRECT:
5685 case HCI_AUTO_CONN_ALWAYS:
5686 if (!is_connected(hdev, addr, addr_type)) {
5687 list_add(&params->action, &hdev->pend_le_conns);
5688 __hci_update_background_scan(req);
5689 }
5690 break;
5691 }
5692
5693 params->auto_connect = auto_connect;
5694
5695 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5696 auto_connect);
5697
5698 return 0;
5699}
5700
Marcel Holtmann8afef092014-06-29 22:28:34 +02005701static void device_added(struct sock *sk, struct hci_dev *hdev,
5702 bdaddr_t *bdaddr, u8 type, u8 action)
5703{
5704 struct mgmt_ev_device_added ev;
5705
5706 bacpy(&ev.addr.bdaddr, bdaddr);
5707 ev.addr.type = type;
5708 ev.action = action;
5709
5710 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5711}
5712
Marcel Holtmann1904a852015-01-11 13:50:44 -08005713static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005714{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005715 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005716
5717 BT_DBG("status 0x%02x", status);
5718
5719 hci_dev_lock(hdev);
5720
5721 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5722 if (!cmd)
5723 goto unlock;
5724
5725 cmd->cmd_complete(cmd, mgmt_status(status));
5726 mgmt_pending_remove(cmd);
5727
5728unlock:
5729 hci_dev_unlock(hdev);
5730}
5731
Marcel Holtmann2faade52014-06-29 19:44:03 +02005732static int add_device(struct sock *sk, struct hci_dev *hdev,
5733 void *data, u16 len)
5734{
5735 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005736 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005737 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005738 u8 auto_conn, addr_type;
5739 int err;
5740
5741 BT_DBG("%s", hdev->name);
5742
Johan Hedberg66593582014-07-09 12:59:14 +03005743 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005744 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005745 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5746 MGMT_STATUS_INVALID_PARAMS,
5747 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005748
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005749 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005750 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5751 MGMT_STATUS_INVALID_PARAMS,
5752 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005753
Johan Hedberg5a154e62014-12-19 22:26:02 +02005754 hci_req_init(&req, hdev);
5755
Marcel Holtmann2faade52014-06-29 19:44:03 +02005756 hci_dev_lock(hdev);
5757
Johan Hedberg5a154e62014-12-19 22:26:02 +02005758 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5759 if (!cmd) {
5760 err = -ENOMEM;
5761 goto unlock;
5762 }
5763
5764 cmd->cmd_complete = addr_cmd_complete;
5765
Johan Hedberg66593582014-07-09 12:59:14 +03005766 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005767 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005768 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005769 err = cmd->cmd_complete(cmd,
5770 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005771 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005772 goto unlock;
5773 }
5774
5775 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5776 cp->addr.type);
5777 if (err)
5778 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005779
Johan Hedberg5a154e62014-12-19 22:26:02 +02005780 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005781
Johan Hedberg66593582014-07-09 12:59:14 +03005782 goto added;
5783 }
5784
Marcel Holtmann2faade52014-06-29 19:44:03 +02005785 if (cp->addr.type == BDADDR_LE_PUBLIC)
5786 addr_type = ADDR_LE_DEV_PUBLIC;
5787 else
5788 addr_type = ADDR_LE_DEV_RANDOM;
5789
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005790 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005791 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005792 else if (cp->action == 0x01)
5793 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005794 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005795 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005796
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005797 /* If the connection parameters don't exist for this device,
5798 * they will be created and configured with defaults.
5799 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005800 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005801 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005802 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005803 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005804 goto unlock;
5805 }
5806
Johan Hedberg66593582014-07-09 12:59:14 +03005807added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005808 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5809
Johan Hedberg5a154e62014-12-19 22:26:02 +02005810 err = hci_req_run(&req, add_device_complete);
5811 if (err < 0) {
5812 /* ENODATA means no HCI commands were needed (e.g. if
5813 * the adapter is powered off).
5814 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005815 if (err == -ENODATA)
5816 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005817 mgmt_pending_remove(cmd);
5818 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005819
5820unlock:
5821 hci_dev_unlock(hdev);
5822 return err;
5823}
5824
Marcel Holtmann8afef092014-06-29 22:28:34 +02005825static void device_removed(struct sock *sk, struct hci_dev *hdev,
5826 bdaddr_t *bdaddr, u8 type)
5827{
5828 struct mgmt_ev_device_removed ev;
5829
5830 bacpy(&ev.addr.bdaddr, bdaddr);
5831 ev.addr.type = type;
5832
5833 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5834}
5835
Marcel Holtmann1904a852015-01-11 13:50:44 -08005836static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005837{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005838 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005839
5840 BT_DBG("status 0x%02x", status);
5841
5842 hci_dev_lock(hdev);
5843
5844 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5845 if (!cmd)
5846 goto unlock;
5847
5848 cmd->cmd_complete(cmd, mgmt_status(status));
5849 mgmt_pending_remove(cmd);
5850
5851unlock:
5852 hci_dev_unlock(hdev);
5853}
5854
Marcel Holtmann2faade52014-06-29 19:44:03 +02005855static int remove_device(struct sock *sk, struct hci_dev *hdev,
5856 void *data, u16 len)
5857{
5858 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005859 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005860 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005861 int err;
5862
5863 BT_DBG("%s", hdev->name);
5864
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005865 hci_req_init(&req, hdev);
5866
Marcel Holtmann2faade52014-06-29 19:44:03 +02005867 hci_dev_lock(hdev);
5868
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005869 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5870 if (!cmd) {
5871 err = -ENOMEM;
5872 goto unlock;
5873 }
5874
5875 cmd->cmd_complete = addr_cmd_complete;
5876
Marcel Holtmann2faade52014-06-29 19:44:03 +02005877 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005878 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005879 u8 addr_type;
5880
Johan Hedberg66593582014-07-09 12:59:14 +03005881 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005882 err = cmd->cmd_complete(cmd,
5883 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005884 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005885 goto unlock;
5886 }
5887
Johan Hedberg66593582014-07-09 12:59:14 +03005888 if (cp->addr.type == BDADDR_BREDR) {
5889 err = hci_bdaddr_list_del(&hdev->whitelist,
5890 &cp->addr.bdaddr,
5891 cp->addr.type);
5892 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005893 err = cmd->cmd_complete(cmd,
5894 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005895 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005896 goto unlock;
5897 }
5898
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005899 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005900
Johan Hedberg66593582014-07-09 12:59:14 +03005901 device_removed(sk, hdev, &cp->addr.bdaddr,
5902 cp->addr.type);
5903 goto complete;
5904 }
5905
Marcel Holtmann2faade52014-06-29 19:44:03 +02005906 if (cp->addr.type == BDADDR_LE_PUBLIC)
5907 addr_type = ADDR_LE_DEV_PUBLIC;
5908 else
5909 addr_type = ADDR_LE_DEV_RANDOM;
5910
Johan Hedbergc71593d2014-07-02 17:37:28 +03005911 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5912 addr_type);
5913 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005914 err = cmd->cmd_complete(cmd,
5915 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005916 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005917 goto unlock;
5918 }
5919
5920 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005921 err = cmd->cmd_complete(cmd,
5922 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005923 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005924 goto unlock;
5925 }
5926
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005927 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005928 list_del(&params->list);
5929 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005930 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005931
5932 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005933 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005934 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005935 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005936
Marcel Holtmann2faade52014-06-29 19:44:03 +02005937 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005938 err = cmd->cmd_complete(cmd,
5939 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005940 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005941 goto unlock;
5942 }
5943
Johan Hedberg66593582014-07-09 12:59:14 +03005944 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5945 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5946 list_del(&b->list);
5947 kfree(b);
5948 }
5949
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005950 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005951
Johan Hedberg19de0822014-07-06 13:06:51 +03005952 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5953 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5954 continue;
5955 device_removed(sk, hdev, &p->addr, p->addr_type);
5956 list_del(&p->action);
5957 list_del(&p->list);
5958 kfree(p);
5959 }
5960
5961 BT_DBG("All LE connection parameters were removed");
5962
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005963 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005964 }
5965
Johan Hedberg66593582014-07-09 12:59:14 +03005966complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005967 err = hci_req_run(&req, remove_device_complete);
5968 if (err < 0) {
5969 /* ENODATA means no HCI commands were needed (e.g. if
5970 * the adapter is powered off).
5971 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005972 if (err == -ENODATA)
5973 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005974 mgmt_pending_remove(cmd);
5975 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005976
5977unlock:
5978 hci_dev_unlock(hdev);
5979 return err;
5980}
5981
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005982static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5983 u16 len)
5984{
5985 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005986 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5987 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005988 u16 param_count, expected_len;
5989 int i;
5990
5991 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005992 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5993 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005994
5995 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005996 if (param_count > max_param_count) {
5997 BT_ERR("load_conn_param: too big param_count value %u",
5998 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005999 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6000 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006001 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006002
6003 expected_len = sizeof(*cp) + param_count *
6004 sizeof(struct mgmt_conn_param);
6005 if (expected_len != len) {
6006 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6007 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006008 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6009 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006010 }
6011
6012 BT_DBG("%s param_count %u", hdev->name, param_count);
6013
6014 hci_dev_lock(hdev);
6015
6016 hci_conn_params_clear_disabled(hdev);
6017
6018 for (i = 0; i < param_count; i++) {
6019 struct mgmt_conn_param *param = &cp->params[i];
6020 struct hci_conn_params *hci_param;
6021 u16 min, max, latency, timeout;
6022 u8 addr_type;
6023
6024 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6025 param->addr.type);
6026
6027 if (param->addr.type == BDADDR_LE_PUBLIC) {
6028 addr_type = ADDR_LE_DEV_PUBLIC;
6029 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6030 addr_type = ADDR_LE_DEV_RANDOM;
6031 } else {
6032 BT_ERR("Ignoring invalid connection parameters");
6033 continue;
6034 }
6035
6036 min = le16_to_cpu(param->min_interval);
6037 max = le16_to_cpu(param->max_interval);
6038 latency = le16_to_cpu(param->latency);
6039 timeout = le16_to_cpu(param->timeout);
6040
6041 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6042 min, max, latency, timeout);
6043
6044 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6045 BT_ERR("Ignoring invalid connection parameters");
6046 continue;
6047 }
6048
6049 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6050 addr_type);
6051 if (!hci_param) {
6052 BT_ERR("Failed to add connection parameters");
6053 continue;
6054 }
6055
6056 hci_param->conn_min_interval = min;
6057 hci_param->conn_max_interval = max;
6058 hci_param->conn_latency = latency;
6059 hci_param->supervision_timeout = timeout;
6060 }
6061
6062 hci_dev_unlock(hdev);
6063
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006064 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6065 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006066}
6067
Marcel Holtmanndbece372014-07-04 18:11:55 +02006068static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6069 void *data, u16 len)
6070{
6071 struct mgmt_cp_set_external_config *cp = data;
6072 bool changed;
6073 int err;
6074
6075 BT_DBG("%s", hdev->name);
6076
6077 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006078 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6079 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006080
6081 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006082 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6083 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006084
6085 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006086 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6087 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006088
6089 hci_dev_lock(hdev);
6090
6091 if (cp->config)
6092 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6093 &hdev->dev_flags);
6094 else
6095 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6096 &hdev->dev_flags);
6097
6098 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6099 if (err < 0)
6100 goto unlock;
6101
6102 if (!changed)
6103 goto unlock;
6104
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006105 err = new_options(hdev, sk);
6106
Marcel Holtmanndbece372014-07-04 18:11:55 +02006107 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
6108 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006109
6110 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6111 set_bit(HCI_CONFIG, &hdev->dev_flags);
6112 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6113
6114 queue_work(hdev->req_workqueue, &hdev->power_on);
6115 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006116 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006117 mgmt_index_added(hdev);
6118 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006119 }
6120
6121unlock:
6122 hci_dev_unlock(hdev);
6123 return err;
6124}
6125
Marcel Holtmann9713c172014-07-06 12:11:15 +02006126static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6127 void *data, u16 len)
6128{
6129 struct mgmt_cp_set_public_address *cp = data;
6130 bool changed;
6131 int err;
6132
6133 BT_DBG("%s", hdev->name);
6134
6135 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006136 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6137 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006138
6139 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006140 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6141 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006142
6143 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006144 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6145 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006146
6147 hci_dev_lock(hdev);
6148
6149 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6150 bacpy(&hdev->public_addr, &cp->bdaddr);
6151
6152 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6153 if (err < 0)
6154 goto unlock;
6155
6156 if (!changed)
6157 goto unlock;
6158
6159 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6160 err = new_options(hdev, sk);
6161
6162 if (is_configured(hdev)) {
6163 mgmt_index_removed(hdev);
6164
6165 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6166
6167 set_bit(HCI_CONFIG, &hdev->dev_flags);
6168 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6169
6170 queue_work(hdev->req_workqueue, &hdev->power_on);
6171 }
6172
6173unlock:
6174 hci_dev_unlock(hdev);
6175 return err;
6176}
6177
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006178static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006179 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006180 { read_version, MGMT_READ_VERSION_SIZE,
6181 HCI_MGMT_NO_HDEV },
6182 { read_commands, MGMT_READ_COMMANDS_SIZE,
6183 HCI_MGMT_NO_HDEV },
6184 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6185 HCI_MGMT_NO_HDEV },
6186 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6187 { set_powered, MGMT_SETTING_SIZE, 0 },
6188 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6189 { set_connectable, MGMT_SETTING_SIZE, 0 },
6190 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6191 { set_bondable, MGMT_SETTING_SIZE, 0 },
6192 { set_link_security, MGMT_SETTING_SIZE, 0 },
6193 { set_ssp, MGMT_SETTING_SIZE, 0 },
6194 { set_hs, MGMT_SETTING_SIZE, 0 },
6195 { set_le, MGMT_SETTING_SIZE, 0 },
6196 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6197 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6198 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6199 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6200 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6201 HCI_MGMT_VAR_LEN },
6202 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6203 HCI_MGMT_VAR_LEN },
6204 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6205 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6206 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6207 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6208 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6209 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6210 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6211 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6212 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6213 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6214 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6215 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6216 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6217 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6218 HCI_MGMT_VAR_LEN },
6219 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6220 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6221 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6222 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6223 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6224 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6225 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6226 { set_advertising, MGMT_SETTING_SIZE, 0 },
6227 { set_bredr, MGMT_SETTING_SIZE, 0 },
6228 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6229 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6230 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6231 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6232 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6233 { load_irks, MGMT_LOAD_IRKS_SIZE,
6234 HCI_MGMT_VAR_LEN },
6235 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6236 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6237 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6238 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6239 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6240 HCI_MGMT_VAR_LEN },
6241 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6242 HCI_MGMT_NO_HDEV },
6243 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6244 HCI_MGMT_UNCONFIGURED },
6245 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6246 HCI_MGMT_UNCONFIGURED },
6247 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6248 HCI_MGMT_UNCONFIGURED },
6249 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6250 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006251};
6252
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006253int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6254 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006255{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006256 void *buf;
6257 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006258 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006259 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006260 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006261 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006262 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006263 int err;
6264
6265 BT_DBG("got %zu bytes", msglen);
6266
6267 if (msglen < sizeof(*hdr))
6268 return -EINVAL;
6269
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006270 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006271 if (!buf)
6272 return -ENOMEM;
6273
Al Viro6ce8e9c2014-04-06 21:25:44 -04006274 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006275 err = -EFAULT;
6276 goto done;
6277 }
6278
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006279 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006280 opcode = __le16_to_cpu(hdr->opcode);
6281 index = __le16_to_cpu(hdr->index);
6282 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006283
6284 if (len != msglen - sizeof(*hdr)) {
6285 err = -EINVAL;
6286 goto done;
6287 }
6288
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006289 if (opcode >= chan->handler_count ||
6290 chan->handlers[opcode].func == NULL) {
6291 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006292 err = mgmt_cmd_status(sk, index, opcode,
6293 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006294 goto done;
6295 }
6296
6297 handler = &chan->handlers[opcode];
6298
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006299 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006300 hdev = hci_dev_get(index);
6301 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006302 err = mgmt_cmd_status(sk, index, opcode,
6303 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006304 goto done;
6305 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006306
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006307 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02006308 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006309 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006310 err = mgmt_cmd_status(sk, index, opcode,
6311 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006312 goto done;
6313 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006314
6315 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006316 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006317 err = mgmt_cmd_status(sk, index, opcode,
6318 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006319 goto done;
6320 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006321 }
6322
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006323 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6324 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006325 err = mgmt_cmd_status(sk, index, opcode,
6326 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006327 goto done;
6328 }
6329
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006330 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6331 if ((var_len && len < handler->data_len) ||
6332 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006333 err = mgmt_cmd_status(sk, index, opcode,
6334 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006335 goto done;
6336 }
6337
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006338 if (hdev)
6339 mgmt_init_hdev(sk, hdev);
6340
6341 cp = buf + sizeof(*hdr);
6342
Johan Hedbergbe22b542012-03-01 22:24:41 +02006343 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006344 if (err < 0)
6345 goto done;
6346
Johan Hedberg03811012010-12-08 00:21:06 +02006347 err = msglen;
6348
6349done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006350 if (hdev)
6351 hci_dev_put(hdev);
6352
Johan Hedberg03811012010-12-08 00:21:06 +02006353 kfree(buf);
6354 return err;
6355}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006356
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006357void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006358{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006359 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006360 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006361
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006362 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6363 return;
6364
6365 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6366 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6367 else
6368 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006369}
6370
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006371void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006372{
Johan Hedberg5f159032012-03-02 03:13:19 +02006373 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006374
Marcel Holtmann1514b892013-10-06 08:25:01 -07006375 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006376 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006377
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006378 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6379 return;
6380
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006381 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006382
Marcel Holtmannedd38962014-07-02 21:30:55 +02006383 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6384 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6385 else
6386 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006387}
6388
Andre Guedes6046dc32014-02-26 20:21:51 -03006389/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006390static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006391{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006392 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006393 struct hci_conn_params *p;
6394
6395 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006396 /* Needed for AUTO_OFF case where might not "really"
6397 * have been powered off.
6398 */
6399 list_del_init(&p->action);
6400
6401 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006402 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006403 case HCI_AUTO_CONN_ALWAYS:
6404 list_add(&p->action, &hdev->pend_le_conns);
6405 break;
6406 case HCI_AUTO_CONN_REPORT:
6407 list_add(&p->action, &hdev->pend_le_reports);
6408 break;
6409 default:
6410 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006411 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006412 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006413
Johan Hedberg2cf22212014-12-19 22:26:00 +02006414 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006415}
6416
Marcel Holtmann1904a852015-01-11 13:50:44 -08006417static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006418{
6419 struct cmd_lookup match = { NULL, hdev };
6420
6421 BT_DBG("status 0x%02x", status);
6422
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006423 if (!status) {
6424 /* Register the available SMP channels (BR/EDR and LE) only
6425 * when successfully powering on the controller. This late
6426 * registration is required so that LE SMP can clearly
6427 * decide if the public address or static address is used.
6428 */
6429 smp_register(hdev);
6430 }
6431
Johan Hedberg229ab392013-03-15 17:06:53 -05006432 hci_dev_lock(hdev);
6433
6434 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6435
6436 new_settings(hdev, match.sk);
6437
6438 hci_dev_unlock(hdev);
6439
6440 if (match.sk)
6441 sock_put(match.sk);
6442}
6443
Johan Hedberg70da6242013-03-15 17:06:51 -05006444static int powered_update_hci(struct hci_dev *hdev)
6445{
Johan Hedberg890ea892013-03-15 17:06:52 -05006446 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006447 u8 link_sec;
6448
Johan Hedberg890ea892013-03-15 17:06:52 -05006449 hci_req_init(&req, hdev);
6450
Johan Hedberg70da6242013-03-15 17:06:51 -05006451 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6452 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006453 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006454
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006455 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006456
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006457 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6458 u8 support = 0x01;
6459
6460 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6461 sizeof(support), &support);
6462 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006463 }
6464
Johan Hedbergc73eee92013-04-19 18:35:21 +03006465 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6466 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006467 struct hci_cp_write_le_host_supported cp;
6468
Marcel Holtmann32226e42014-07-24 20:04:16 +02006469 cp.le = 0x01;
6470 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006471
6472 /* Check first if we already have the right
6473 * host state (host features set)
6474 */
6475 if (cp.le != lmp_host_le_capable(hdev) ||
6476 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006477 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6478 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006479 }
6480
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006481 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006482 /* Make sure the controller has a good default for
6483 * advertising data. This also applies to the case
6484 * where BR/EDR was toggled during the AUTO_OFF phase.
6485 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006486 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006487 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006488 update_scan_rsp_data(&req);
6489 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006490
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006491 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6492 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006493
6494 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006495 }
6496
Johan Hedberg70da6242013-03-15 17:06:51 -05006497 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6498 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006499 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6500 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006501
6502 if (lmp_bredr_capable(hdev)) {
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006503 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
6504 write_fast_connectable(&req, true);
6505 else
6506 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006507 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006508 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006509 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006510 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006511 }
6512
Johan Hedberg229ab392013-03-15 17:06:53 -05006513 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006514}
6515
Johan Hedberg744cf192011-11-08 20:40:14 +02006516int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006517{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006518 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006519 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006520 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006521
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006522 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6523 return 0;
6524
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006525 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006526 if (powered_update_hci(hdev) == 0)
6527 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006528
Johan Hedberg229ab392013-03-15 17:06:53 -05006529 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6530 &match);
6531 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006532 }
6533
Johan Hedberg229ab392013-03-15 17:06:53 -05006534 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006535
6536 /* If the power off is because of hdev unregistration let
6537 * use the appropriate INVALID_INDEX status. Otherwise use
6538 * NOT_POWERED. We cover both scenarios here since later in
6539 * mgmt_index_removed() any hci_conn callbacks will have already
6540 * been triggered, potentially causing misleading DISCONNECTED
6541 * status responses.
6542 */
6543 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6544 status = MGMT_STATUS_INVALID_INDEX;
6545 else
6546 status = MGMT_STATUS_NOT_POWERED;
6547
6548 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006549
6550 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6551 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6552 zero_cod, sizeof(zero_cod), NULL);
6553
6554new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006555 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006556
6557 if (match.sk)
6558 sock_put(match.sk);
6559
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006560 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006561}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006562
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006563void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006564{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006565 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006566 u8 status;
6567
6568 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6569 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006570 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006571
6572 if (err == -ERFKILL)
6573 status = MGMT_STATUS_RFKILLED;
6574 else
6575 status = MGMT_STATUS_FAILED;
6576
Johan Hedberga69e8372015-03-06 21:08:53 +02006577 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006578
6579 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006580}
6581
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006582void mgmt_discoverable_timeout(struct hci_dev *hdev)
6583{
6584 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006585
6586 hci_dev_lock(hdev);
6587
6588 /* When discoverable timeout triggers, then just make sure
6589 * the limited discoverable flag is cleared. Even in the case
6590 * of a timeout triggered from general discoverable, it is
6591 * safe to unconditionally clear the flag.
6592 */
6593 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006594 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006595
6596 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006597 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6598 u8 scan = SCAN_PAGE;
6599 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6600 sizeof(scan), &scan);
6601 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006602 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006603 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006604 hci_req_run(&req, NULL);
6605
6606 hdev->discov_timeout = 0;
6607
Johan Hedberg9a43e252013-10-20 19:00:07 +03006608 new_settings(hdev, NULL);
6609
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006610 hci_dev_unlock(hdev);
6611}
6612
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006613void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6614 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006615{
Johan Hedberg86742e12011-11-07 23:13:38 +02006616 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006617
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006618 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006619
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006620 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006621 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006622 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006623 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006624 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006625 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006626
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006627 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006628}
Johan Hedbergf7520542011-01-20 12:34:39 +02006629
Johan Hedbergd7b25452014-05-23 13:19:53 +03006630static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6631{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006632 switch (ltk->type) {
6633 case SMP_LTK:
6634 case SMP_LTK_SLAVE:
6635 if (ltk->authenticated)
6636 return MGMT_LTK_AUTHENTICATED;
6637 return MGMT_LTK_UNAUTHENTICATED;
6638 case SMP_LTK_P256:
6639 if (ltk->authenticated)
6640 return MGMT_LTK_P256_AUTH;
6641 return MGMT_LTK_P256_UNAUTH;
6642 case SMP_LTK_P256_DEBUG:
6643 return MGMT_LTK_P256_DEBUG;
6644 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006645
6646 return MGMT_LTK_UNAUTHENTICATED;
6647}
6648
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006649void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006650{
6651 struct mgmt_ev_new_long_term_key ev;
6652
6653 memset(&ev, 0, sizeof(ev));
6654
Marcel Holtmann5192d302014-02-19 17:11:58 -08006655 /* Devices using resolvable or non-resolvable random addresses
6656 * without providing an indentity resolving key don't require
6657 * to store long term keys. Their addresses will change the
6658 * next time around.
6659 *
6660 * Only when a remote device provides an identity address
6661 * make sure the long term key is stored. If the remote
6662 * identity is known, the long term keys are internally
6663 * mapped to the identity address. So allow static random
6664 * and public addresses here.
6665 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006666 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6667 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6668 ev.store_hint = 0x00;
6669 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006670 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006671
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006672 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006673 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006674 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006675 ev.key.enc_size = key->enc_size;
6676 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006677 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006678
Johan Hedberg2ceba532014-06-16 19:25:16 +03006679 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006680 ev.key.master = 1;
6681
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006682 memcpy(ev.key.val, key->val, sizeof(key->val));
6683
Marcel Holtmann083368f2013-10-15 14:26:29 -07006684 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006685}
6686
Johan Hedberg95fbac82014-02-19 15:18:31 +02006687void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6688{
6689 struct mgmt_ev_new_irk ev;
6690
6691 memset(&ev, 0, sizeof(ev));
6692
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006693 /* For identity resolving keys from devices that are already
6694 * using a public address or static random address, do not
6695 * ask for storing this key. The identity resolving key really
6696 * is only mandatory for devices using resovlable random
6697 * addresses.
6698 *
6699 * Storing all identity resolving keys has the downside that
6700 * they will be also loaded on next boot of they system. More
6701 * identity resolving keys, means more time during scanning is
6702 * needed to actually resolve these addresses.
6703 */
6704 if (bacmp(&irk->rpa, BDADDR_ANY))
6705 ev.store_hint = 0x01;
6706 else
6707 ev.store_hint = 0x00;
6708
Johan Hedberg95fbac82014-02-19 15:18:31 +02006709 bacpy(&ev.rpa, &irk->rpa);
6710 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6711 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6712 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6713
6714 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6715}
6716
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006717void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6718 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006719{
6720 struct mgmt_ev_new_csrk ev;
6721
6722 memset(&ev, 0, sizeof(ev));
6723
6724 /* Devices using resolvable or non-resolvable random addresses
6725 * without providing an indentity resolving key don't require
6726 * to store signature resolving keys. Their addresses will change
6727 * the next time around.
6728 *
6729 * Only when a remote device provides an identity address
6730 * make sure the signature resolving key is stored. So allow
6731 * static random and public addresses here.
6732 */
6733 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6734 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6735 ev.store_hint = 0x00;
6736 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006737 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006738
6739 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6740 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006741 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006742 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6743
6744 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6745}
6746
Andre Guedesffb5a8272014-07-01 18:10:11 -03006747void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006748 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6749 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006750{
6751 struct mgmt_ev_new_conn_param ev;
6752
Johan Hedbergc103aea2014-07-02 17:37:34 +03006753 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6754 return;
6755
Andre Guedesffb5a8272014-07-01 18:10:11 -03006756 memset(&ev, 0, sizeof(ev));
6757 bacpy(&ev.addr.bdaddr, bdaddr);
6758 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006759 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006760 ev.min_interval = cpu_to_le16(min_interval);
6761 ev.max_interval = cpu_to_le16(max_interval);
6762 ev.latency = cpu_to_le16(latency);
6763 ev.timeout = cpu_to_le16(timeout);
6764
6765 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6766}
6767
Marcel Holtmann94933992013-10-15 10:26:39 -07006768static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6769 u8 data_len)
6770{
6771 eir[eir_len++] = sizeof(type) + data_len;
6772 eir[eir_len++] = type;
6773 memcpy(&eir[eir_len], data, data_len);
6774 eir_len += data_len;
6775
6776 return eir_len;
6777}
6778
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006779void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6780 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006781{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006782 char buf[512];
6783 struct mgmt_ev_device_connected *ev = (void *) buf;
6784 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006785
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006786 bacpy(&ev->addr.bdaddr, &conn->dst);
6787 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006788
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006789 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006790
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006791 /* We must ensure that the EIR Data fields are ordered and
6792 * unique. Keep it simple for now and avoid the problem by not
6793 * adding any BR/EDR data to the LE adv.
6794 */
6795 if (conn->le_adv_data_len > 0) {
6796 memcpy(&ev->eir[eir_len],
6797 conn->le_adv_data, conn->le_adv_data_len);
6798 eir_len = conn->le_adv_data_len;
6799 } else {
6800 if (name_len > 0)
6801 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6802 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006803
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006804 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006805 eir_len = eir_append_data(ev->eir, eir_len,
6806 EIR_CLASS_OF_DEV,
6807 conn->dev_class, 3);
6808 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006809
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006810 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006811
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006812 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6813 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006814}
6815
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006816static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006817{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006818 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006819
Johan Hedbergf5818c22014-12-05 13:36:02 +02006820 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006821
6822 *sk = cmd->sk;
6823 sock_hold(*sk);
6824
Johan Hedberga664b5b2011-02-19 12:06:02 -03006825 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006826}
6827
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006828static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006829{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006830 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006831 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006832
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006833 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6834
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006835 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006836 mgmt_pending_remove(cmd);
6837}
6838
Johan Hedberg84c61d92014-08-01 11:13:30 +03006839bool mgmt_powering_down(struct hci_dev *hdev)
6840{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006841 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006842 struct mgmt_mode *cp;
6843
6844 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6845 if (!cmd)
6846 return false;
6847
6848 cp = cmd->param;
6849 if (!cp->val)
6850 return true;
6851
6852 return false;
6853}
6854
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006855void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006856 u8 link_type, u8 addr_type, u8 reason,
6857 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006858{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006859 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006860 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006861
Johan Hedberg84c61d92014-08-01 11:13:30 +03006862 /* The connection is still in hci_conn_hash so test for 1
6863 * instead of 0 to know if this is the last one.
6864 */
6865 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6866 cancel_delayed_work(&hdev->power_off);
6867 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006868 }
6869
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006870 if (!mgmt_connected)
6871 return;
6872
Andre Guedes57eb7762013-10-30 19:01:41 -03006873 if (link_type != ACL_LINK && link_type != LE_LINK)
6874 return;
6875
Johan Hedberg744cf192011-11-08 20:40:14 +02006876 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006877
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006878 bacpy(&ev.addr.bdaddr, bdaddr);
6879 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6880 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006881
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006882 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006883
6884 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006885 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006886
Johan Hedberg124f6e32012-02-09 13:50:12 +02006887 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006888 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006889}
6890
Marcel Holtmann78929242013-10-06 23:55:47 -07006891void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6892 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006893{
Andre Guedes3655bba2013-10-30 19:01:40 -03006894 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6895 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006896 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006897
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006898 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6899 hdev);
6900
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006901 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006902 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006903 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006904
Andre Guedes3655bba2013-10-30 19:01:40 -03006905 cp = cmd->param;
6906
6907 if (bacmp(bdaddr, &cp->addr.bdaddr))
6908 return;
6909
6910 if (cp->addr.type != bdaddr_type)
6911 return;
6912
Johan Hedbergf5818c22014-12-05 13:36:02 +02006913 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006914 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006915}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006916
Marcel Holtmann445608d2013-10-06 23:55:48 -07006917void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6918 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006919{
6920 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006921
Johan Hedberg84c61d92014-08-01 11:13:30 +03006922 /* The connection is still in hci_conn_hash so test for 1
6923 * instead of 0 to know if this is the last one.
6924 */
6925 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6926 cancel_delayed_work(&hdev->power_off);
6927 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006928 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006929
Johan Hedberg4c659c32011-11-07 23:13:39 +02006930 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006931 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006932 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006933
Marcel Holtmann445608d2013-10-06 23:55:48 -07006934 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006935}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006936
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006937void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006938{
6939 struct mgmt_ev_pin_code_request ev;
6940
Johan Hedbergd8457692012-02-17 14:24:57 +02006941 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006942 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006943 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006944
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006945 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006946}
6947
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006948void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6949 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006950{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006951 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006952
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006953 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006954 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006955 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006956
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006957 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006958 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006959}
6960
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006961void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6962 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006963{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006964 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006965
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006966 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006967 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006968 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006969
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006970 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006971 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006972}
Johan Hedberga5c29682011-02-19 12:05:57 -03006973
Johan Hedberg744cf192011-11-08 20:40:14 +02006974int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006975 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006976 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006977{
6978 struct mgmt_ev_user_confirm_request ev;
6979
Johan Hedberg744cf192011-11-08 20:40:14 +02006980 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006981
Johan Hedberg272d90d2012-02-09 15:26:12 +02006982 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006983 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006984 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006985 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006986
Johan Hedberg744cf192011-11-08 20:40:14 +02006987 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006988 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006989}
6990
Johan Hedberg272d90d2012-02-09 15:26:12 +02006991int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006992 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006993{
6994 struct mgmt_ev_user_passkey_request ev;
6995
6996 BT_DBG("%s", hdev->name);
6997
Johan Hedberg272d90d2012-02-09 15:26:12 +02006998 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006999 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007000
7001 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007002 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007003}
7004
Brian Gix0df4c182011-11-16 13:53:13 -08007005static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007006 u8 link_type, u8 addr_type, u8 status,
7007 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007008{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007009 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007010
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007011 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007012 if (!cmd)
7013 return -ENOENT;
7014
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007015 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007016 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007017
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007018 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007019}
7020
Johan Hedberg744cf192011-11-08 20:40:14 +02007021int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007022 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007023{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007024 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007025 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007026}
7027
Johan Hedberg272d90d2012-02-09 15:26:12 +02007028int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007029 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007030{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007031 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007032 status,
7033 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007034}
Johan Hedberg2a611692011-02-19 12:06:00 -03007035
Brian Gix604086b2011-11-23 08:28:33 -08007036int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007037 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007038{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007039 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007040 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007041}
7042
Johan Hedberg272d90d2012-02-09 15:26:12 +02007043int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007044 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007045{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007046 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007047 status,
7048 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007049}
7050
Johan Hedberg92a25252012-09-06 18:39:26 +03007051int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7052 u8 link_type, u8 addr_type, u32 passkey,
7053 u8 entered)
7054{
7055 struct mgmt_ev_passkey_notify ev;
7056
7057 BT_DBG("%s", hdev->name);
7058
7059 bacpy(&ev.addr.bdaddr, bdaddr);
7060 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7061 ev.passkey = __cpu_to_le32(passkey);
7062 ev.entered = entered;
7063
7064 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7065}
7066
Johan Hedberge1e930f2014-09-08 17:09:49 -07007067void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007068{
7069 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007070 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007071 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007072
Johan Hedberge1e930f2014-09-08 17:09:49 -07007073 bacpy(&ev.addr.bdaddr, &conn->dst);
7074 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7075 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007076
Johan Hedberge1e930f2014-09-08 17:09:49 -07007077 cmd = find_pairing(conn);
7078
7079 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7080 cmd ? cmd->sk : NULL);
7081
Johan Hedberga511b352014-12-11 21:45:45 +02007082 if (cmd) {
7083 cmd->cmd_complete(cmd, status);
7084 mgmt_pending_remove(cmd);
7085 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007086}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007087
Marcel Holtmann464996a2013-10-15 14:26:24 -07007088void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007089{
7090 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007091 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007092
7093 if (status) {
7094 u8 mgmt_err = mgmt_status(status);
7095 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007096 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007097 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007098 }
7099
Marcel Holtmann464996a2013-10-15 14:26:24 -07007100 if (test_bit(HCI_AUTH, &hdev->flags))
7101 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7102 &hdev->dev_flags);
7103 else
7104 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7105 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007106
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007107 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007108 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007109
Johan Hedberg47990ea2012-02-22 11:58:37 +02007110 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007111 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007112
7113 if (match.sk)
7114 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007115}
7116
Johan Hedberg890ea892013-03-15 17:06:52 -05007117static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007118{
Johan Hedberg890ea892013-03-15 17:06:52 -05007119 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007120 struct hci_cp_write_eir cp;
7121
Johan Hedberg976eb202012-10-24 21:12:01 +03007122 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007123 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007124
Johan Hedbergc80da272012-02-22 15:38:48 +02007125 memset(hdev->eir, 0, sizeof(hdev->eir));
7126
Johan Hedbergcacaf522012-02-21 00:52:42 +02007127 memset(&cp, 0, sizeof(cp));
7128
Johan Hedberg890ea892013-03-15 17:06:52 -05007129 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007130}
7131
Marcel Holtmann3e248562013-10-15 14:26:25 -07007132void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007133{
7134 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007135 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007136 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007137
7138 if (status) {
7139 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007140
7141 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007142 &hdev->dev_flags)) {
7143 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007144 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007145 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007146
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007147 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7148 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007149 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007150 }
7151
7152 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007153 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007154 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007155 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7156 if (!changed)
7157 changed = test_and_clear_bit(HCI_HS_ENABLED,
7158 &hdev->dev_flags);
7159 else
7160 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007161 }
7162
7163 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7164
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007165 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007166 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007167
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007168 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007169 sock_put(match.sk);
7170
Johan Hedberg890ea892013-03-15 17:06:52 -05007171 hci_req_init(&req, hdev);
7172
Johan Hedberg37699722014-06-24 14:00:27 +03007173 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
7174 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
7175 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7176 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007177 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007178 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007179 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007180 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007181
7182 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007183}
7184
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007185static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007186{
7187 struct cmd_lookup *match = data;
7188
Johan Hedberg90e70452012-02-23 23:09:40 +02007189 if (match->sk == NULL) {
7190 match->sk = cmd->sk;
7191 sock_hold(match->sk);
7192 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007193}
7194
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007195void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7196 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007197{
Johan Hedberg90e70452012-02-23 23:09:40 +02007198 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007199
Johan Hedberg92da6092013-03-15 17:06:55 -05007200 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7201 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7202 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007203
7204 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007205 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7206 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007207
7208 if (match.sk)
7209 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007210}
7211
Marcel Holtmann7667da32013-10-15 14:26:27 -07007212void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007213{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007214 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007215 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007216
Johan Hedberg13928972013-03-15 17:07:00 -05007217 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007218 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007219
7220 memset(&ev, 0, sizeof(ev));
7221 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007222 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007223
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007224 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007225 if (!cmd) {
7226 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007227
Johan Hedberg13928972013-03-15 17:07:00 -05007228 /* If this is a HCI command related to powering on the
7229 * HCI dev don't send any mgmt signals.
7230 */
7231 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007232 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007233 }
7234
Marcel Holtmann7667da32013-10-15 14:26:27 -07007235 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7236 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007237}
Szymon Jancc35938b2011-03-22 13:12:21 +01007238
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007239void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007240 u8 *rand192, u8 *hash256, u8 *rand256,
7241 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007242{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007243 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007244
Johan Hedberg744cf192011-11-08 20:40:14 +02007245 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007246
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007247 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007248 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007249 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007250
7251 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007252 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7253 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007254 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007255 struct mgmt_rp_read_local_oob_data rp;
7256 size_t rp_size = sizeof(rp);
7257
7258 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7259 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7260
Johan Hedberg710f11c2014-05-26 11:21:22 +03007261 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007262 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007263 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007264 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007265 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007266 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007267
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007268 mgmt_cmd_complete(cmd->sk, hdev->id,
7269 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7270 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007271 }
7272
7273 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007274}
Johan Hedberge17acd42011-03-30 23:57:16 +03007275
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007276static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7277{
7278 int i;
7279
7280 for (i = 0; i < uuid_count; i++) {
7281 if (!memcmp(uuid, uuids[i], 16))
7282 return true;
7283 }
7284
7285 return false;
7286}
7287
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007288static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7289{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007290 u16 parsed = 0;
7291
7292 while (parsed < eir_len) {
7293 u8 field_len = eir[0];
7294 u8 uuid[16];
7295 int i;
7296
7297 if (field_len == 0)
7298 break;
7299
7300 if (eir_len - parsed < field_len + 1)
7301 break;
7302
7303 switch (eir[1]) {
7304 case EIR_UUID16_ALL:
7305 case EIR_UUID16_SOME:
7306 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007307 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007308 uuid[13] = eir[i + 3];
7309 uuid[12] = eir[i + 2];
7310 if (has_uuid(uuid, uuid_count, uuids))
7311 return true;
7312 }
7313 break;
7314 case EIR_UUID32_ALL:
7315 case EIR_UUID32_SOME:
7316 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007317 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007318 uuid[15] = eir[i + 5];
7319 uuid[14] = eir[i + 4];
7320 uuid[13] = eir[i + 3];
7321 uuid[12] = eir[i + 2];
7322 if (has_uuid(uuid, uuid_count, uuids))
7323 return true;
7324 }
7325 break;
7326 case EIR_UUID128_ALL:
7327 case EIR_UUID128_SOME:
7328 for (i = 0; i + 17 <= field_len; i += 16) {
7329 memcpy(uuid, eir + i + 2, 16);
7330 if (has_uuid(uuid, uuid_count, uuids))
7331 return true;
7332 }
7333 break;
7334 }
7335
7336 parsed += field_len + 1;
7337 eir += field_len + 1;
7338 }
7339
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007340 return false;
7341}
7342
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007343static void restart_le_scan(struct hci_dev *hdev)
7344{
7345 /* If controller is not scanning we are done. */
7346 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7347 return;
7348
7349 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7350 hdev->discovery.scan_start +
7351 hdev->discovery.scan_duration))
7352 return;
7353
7354 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7355 DISCOV_LE_RESTART_DELAY);
7356}
7357
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007358static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7359 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7360{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007361 /* If a RSSI threshold has been specified, and
7362 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7363 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7364 * is set, let it through for further processing, as we might need to
7365 * restart the scan.
7366 *
7367 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7368 * the results are also dropped.
7369 */
7370 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7371 (rssi == HCI_RSSI_INVALID ||
7372 (rssi < hdev->discovery.rssi &&
7373 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7374 return false;
7375
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007376 if (hdev->discovery.uuid_count != 0) {
7377 /* If a list of UUIDs is provided in filter, results with no
7378 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007379 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007380 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7381 hdev->discovery.uuids) &&
7382 !eir_has_uuids(scan_rsp, scan_rsp_len,
7383 hdev->discovery.uuid_count,
7384 hdev->discovery.uuids))
7385 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007386 }
7387
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007388 /* If duplicate filtering does not report RSSI changes, then restart
7389 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007390 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007391 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7392 restart_le_scan(hdev);
7393
7394 /* Validate RSSI value against the RSSI threshold once more. */
7395 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7396 rssi < hdev->discovery.rssi)
7397 return false;
7398 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007399
7400 return true;
7401}
7402
Marcel Holtmann901801b2013-10-06 23:55:51 -07007403void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007404 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7405 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007406{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007407 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007408 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007409 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007410
Johan Hedberg75ce2082014-07-02 22:42:01 +03007411 /* Don't send events for a non-kernel initiated discovery. With
7412 * LE one exception is if we have pend_le_reports > 0 in which
7413 * case we're doing passive scanning and want these events.
7414 */
7415 if (!hci_discovery_active(hdev)) {
7416 if (link_type == ACL_LINK)
7417 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007418 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007419 return;
7420 }
Andre Guedes12602d02013-04-30 15:29:40 -03007421
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007422 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007423 /* We are using service discovery */
7424 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7425 scan_rsp_len))
7426 return;
7427 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007428
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007429 /* Make sure that the buffer is big enough. The 5 extra bytes
7430 * are for the potential CoD field.
7431 */
7432 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007433 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007434
Johan Hedberg1dc06092012-01-15 21:01:23 +02007435 memset(buf, 0, sizeof(buf));
7436
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007437 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7438 * RSSI value was reported as 0 when not available. This behavior
7439 * is kept when using device discovery. This is required for full
7440 * backwards compatibility with the API.
7441 *
7442 * However when using service discovery, the value 127 will be
7443 * returned when the RSSI is not available.
7444 */
Szymon Janc91200e92015-01-22 16:57:05 +01007445 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7446 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007447 rssi = 0;
7448
Johan Hedberg841c5642014-07-07 12:45:54 +03007449 bacpy(&ev->addr.bdaddr, bdaddr);
7450 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007451 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007452 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007453
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007454 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007455 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007456 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007457
Johan Hedberg1dc06092012-01-15 21:01:23 +02007458 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7459 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007460 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007461
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007462 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007463 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007464 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007465
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007466 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7467 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007468
Marcel Holtmann901801b2013-10-06 23:55:51 -07007469 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007470}
Johan Hedberga88a9652011-03-30 13:18:12 +03007471
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007472void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7473 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007474{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007475 struct mgmt_ev_device_found *ev;
7476 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7477 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007478
Johan Hedbergb644ba32012-01-17 21:48:47 +02007479 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007480
Johan Hedbergb644ba32012-01-17 21:48:47 +02007481 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007482
Johan Hedbergb644ba32012-01-17 21:48:47 +02007483 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007484 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007485 ev->rssi = rssi;
7486
7487 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007488 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007489
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007490 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007491
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007492 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007493}
Johan Hedberg314b2382011-04-27 10:29:57 -04007494
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007495void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007496{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007497 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007498
Andre Guedes343fb142011-11-22 17:14:19 -03007499 BT_DBG("%s discovering %u", hdev->name, discovering);
7500
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007501 memset(&ev, 0, sizeof(ev));
7502 ev.type = hdev->discovery.type;
7503 ev.discovering = discovering;
7504
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007505 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007506}
Antti Julku5e762442011-08-25 16:48:02 +03007507
Marcel Holtmann1904a852015-01-11 13:50:44 -08007508static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007509{
7510 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007511}
7512
7513void mgmt_reenable_advertising(struct hci_dev *hdev)
7514{
7515 struct hci_request req;
7516
Marcel Holtmann5976e602013-10-06 04:08:14 -07007517 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7518 return;
7519
7520 hci_req_init(&req, hdev);
7521 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007522 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007523}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007524
7525static struct hci_mgmt_chan chan = {
7526 .channel = HCI_CHANNEL_CONTROL,
7527 .handler_count = ARRAY_SIZE(mgmt_handlers),
7528 .handlers = mgmt_handlers,
7529};
7530
7531int mgmt_init(void)
7532{
7533 return hci_mgmt_chan_register(&chan);
7534}
7535
7536void mgmt_exit(void)
7537{
7538 hci_mgmt_chan_unregister(&chan);
7539}