blob: 596b36111e64d9500ed39ae18b068957c6430008 [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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200268
Andre Guedes790eff42012-06-07 19:05:46 -0300269 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200285 kfree_skb(skb);
286
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300287 return err;
Johan Hedbergf7b64e692010-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 Hedbergaee9b212012-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 &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700388 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
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 Holtmannd7a5a112015-03-13 02:11:00 -0700401 if (hci_dev_test_flag(d, HCI_SETUP) ||
402 hci_dev_test_flag(d, HCI_CONFIG) ||
403 hci_dev_test_flag(d, HCI_USER_CHANNEL))
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 &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700413 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
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 &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700448 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200449 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) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700461 if (hci_dev_test_flag(d, HCI_SETUP) ||
462 hci_dev_test_flag(d, HCI_CONFIG) ||
463 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200464 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 &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700473 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200474 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) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700495 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 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) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700510 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
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 Hedbergf7b64e692010-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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700611 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200612 settings |= MGMT_SETTING_CONNECTABLE;
613
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700614 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500615 settings |= MGMT_SETTING_FAST_CONNECTABLE;
616
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700617 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_DISCOVERABLE;
619
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700620 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300621 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200622
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700623 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200624 settings |= MGMT_SETTING_BREDR;
625
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700626 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200627 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200628
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700629 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200630 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200631
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700632 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200633 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200634
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700635 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200636 settings |= MGMT_SETTING_HS;
637
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700638 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300639 settings |= MGMT_SETTING_ADVERTISING;
640
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700641 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800642 settings |= MGMT_SETTING_SECURE_CONN;
643
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700644 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800645 settings |= MGMT_SETTING_DEBUG_KEYS;
646
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700647 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200648 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) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700663 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800664 !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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700843 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
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 {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700877 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300878 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300880 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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700892 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700924 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001012 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001013 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001014
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001015 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001051 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001052 return;
1053
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001054 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
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 Holtmannd7a5a112015-03-13 02:11:00 -07001061 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001062 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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001083 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001103 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001104 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 Holtmannd7a5a112015-03-13 02:11:00 -07001113 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001114 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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001168 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
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 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001331 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001357 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
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;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001541 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001542 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;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001551 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001552 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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001629 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1630 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
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 Hedbergf7b64e692010-12-13 21:07:06 +02001647
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001648 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +02001660 goto failed;
1661 }
1662
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001663 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
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 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001676 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001677 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 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001695 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1696 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1697 HCI_LIMITED_DISCOVERABLE)) {
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 Hedbergf7b64e692010-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 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001735 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001736 goto update_ad;
1737
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +02001774 if (err < 0)
1775 mgmt_pending_remove(cmd);
1776
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001777failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001778 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001788 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001789 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 Hedberge8ba3a1f2013-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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001873 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001874 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 Hedberge8ba3a1f2013-10-19 23:38:18 +03001890 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001891 }
Johan Hedberge8ba3a1f2013-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001907 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1908 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
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 Hedberge8ba3a1f2013-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 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001942 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03001943 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 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001975 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
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
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002048 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002049 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2050 changed = true;
2051 }
2052
2053 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2054 if (err < 0)
2055 goto failed;
2056
2057 if (changed)
2058 err = new_settings(hdev, sk);
2059
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002060 goto failed;
2061 }
2062
2063 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002064 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2065 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002066 goto failed;
2067 }
2068
2069 val = !!cp->val;
2070
2071 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2072 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2073 goto failed;
2074 }
2075
2076 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2077 if (!cmd) {
2078 err = -ENOMEM;
2079 goto failed;
2080 }
2081
2082 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2083 if (err < 0) {
2084 mgmt_pending_remove(cmd);
2085 goto failed;
2086 }
2087
2088failed:
2089 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002090 return err;
2091}
2092
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002093static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002094{
2095 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002096 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002097 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002098 int err;
2099
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002100 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002101
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002102 status = mgmt_bredr_support(hdev);
2103 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002104 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002105
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002106 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002107 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2108 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002109
Johan Hedberga7e80f22013-01-09 16:05:19 +02002110 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002111 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2112 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002113
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002114 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002115
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002116 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002117 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002118
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002119 if (cp->val) {
2120 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2121 &hdev->dev_flags);
2122 } else {
2123 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2124 &hdev->dev_flags);
2125 if (!changed)
2126 changed = test_and_clear_bit(HCI_HS_ENABLED,
2127 &hdev->dev_flags);
2128 else
2129 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002130 }
2131
2132 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2133 if (err < 0)
2134 goto failed;
2135
2136 if (changed)
2137 err = new_settings(hdev, sk);
2138
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002139 goto failed;
2140 }
2141
Johan Hedberg94d52da2015-02-19 17:38:06 +02002142 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002143 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2144 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002145 goto failed;
2146 }
2147
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002148 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002149 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2150 goto failed;
2151 }
2152
2153 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2154 if (!cmd) {
2155 err = -ENOMEM;
2156 goto failed;
2157 }
2158
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002159 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002160 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2161 sizeof(cp->val), &cp->val);
2162
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002163 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002164 if (err < 0) {
2165 mgmt_pending_remove(cmd);
2166 goto failed;
2167 }
2168
2169failed:
2170 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002171 return err;
2172}
2173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002174static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002175{
2176 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002177 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002178 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002179 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002181 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002182
Johan Hedberge6fe7982013-10-02 15:45:22 +03002183 status = mgmt_bredr_support(hdev);
2184 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002185 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002186
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002187 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002188 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2189 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002190
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002191 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002192 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2193 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002194
Johan Hedberga7e80f22013-01-09 16:05:19 +02002195 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002196 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2197 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002198
Marcel Holtmannee392692013-10-01 22:59:23 -07002199 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002200
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002201 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002202 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2203 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002204 goto unlock;
2205 }
2206
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002207 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002208 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002209 } else {
2210 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002211 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2212 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002213 goto unlock;
2214 }
2215
Marcel Holtmannee392692013-10-01 22:59:23 -07002216 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002217 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002218
2219 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2220 if (err < 0)
2221 goto unlock;
2222
2223 if (changed)
2224 err = new_settings(hdev, sk);
2225
2226unlock:
2227 hci_dev_unlock(hdev);
2228 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002229}
2230
Marcel Holtmann1904a852015-01-11 13:50:44 -08002231static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002232{
2233 struct cmd_lookup match = { NULL, hdev };
2234
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302235 hci_dev_lock(hdev);
2236
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002237 if (status) {
2238 u8 mgmt_err = mgmt_status(status);
2239
2240 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2241 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302242 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002243 }
2244
2245 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2246
2247 new_settings(hdev, match.sk);
2248
2249 if (match.sk)
2250 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002251
2252 /* Make sure the controller has a good default for
2253 * advertising data. Restrict the update to when LE
2254 * has actually been enabled. During power on, the
2255 * update in powered_update_hci will take care of it.
2256 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002257 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002258 struct hci_request req;
2259
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002260 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002261 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002262 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002263 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002264 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002265 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302266
2267unlock:
2268 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002269}
2270
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002271static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002272{
2273 struct mgmt_mode *cp = data;
2274 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002275 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002276 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002277 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002278 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002279
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002280 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002281
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002282 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002283 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2284 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002285
Johan Hedberga7e80f22013-01-09 16:05:19 +02002286 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002287 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2288 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002289
Johan Hedbergc73eee92013-04-19 18:35:21 +03002290 /* LE-only devices do not allow toggling LE on/off */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002291 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002292 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2293 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002294
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002295 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002296
2297 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002298 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002300 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 bool changed = false;
2302
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002303 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002304 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2305 changed = true;
2306 }
2307
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002308 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002309 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002310 changed = true;
2311 }
2312
Johan Hedberg06199cf2012-02-22 16:37:11 +02002313 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2314 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002315 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002316
2317 if (changed)
2318 err = new_settings(hdev, sk);
2319
Johan Hedberg1de028c2012-02-29 19:55:35 -08002320 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321 }
2322
Johan Hedberg4375f102013-09-25 13:26:10 +03002323 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2324 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002325 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2326 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002327 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002328 }
2329
2330 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2331 if (!cmd) {
2332 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002333 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002334 }
2335
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002336 hci_req_init(&req, hdev);
2337
Johan Hedberg06199cf2012-02-22 16:37:11 +02002338 memset(&hci_cp, 0, sizeof(hci_cp));
2339
2340 if (val) {
2341 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002342 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002343 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002344 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002345 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002346 }
2347
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002348 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2349 &hci_cp);
2350
2351 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302352 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002353 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002354
Johan Hedberg1de028c2012-02-29 19:55:35 -08002355unlock:
2356 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002357 return err;
2358}
2359
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002360/* This is a helper function to test for pending mgmt commands that can
2361 * cause CoD or EIR HCI commands. We can only allow one such pending
2362 * mgmt command at a time since otherwise we cannot easily track what
2363 * the current values are, will be, and based on that calculate if a new
2364 * HCI command needs to be sent and if yes with what value.
2365 */
2366static bool pending_eir_or_class(struct hci_dev *hdev)
2367{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002368 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002369
2370 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2371 switch (cmd->opcode) {
2372 case MGMT_OP_ADD_UUID:
2373 case MGMT_OP_REMOVE_UUID:
2374 case MGMT_OP_SET_DEV_CLASS:
2375 case MGMT_OP_SET_POWERED:
2376 return true;
2377 }
2378 }
2379
2380 return false;
2381}
2382
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002383static const u8 bluetooth_base_uuid[] = {
2384 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2385 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2386};
2387
2388static u8 get_uuid_size(const u8 *uuid)
2389{
2390 u32 val;
2391
2392 if (memcmp(uuid, bluetooth_base_uuid, 12))
2393 return 128;
2394
2395 val = get_unaligned_le32(&uuid[12]);
2396 if (val > 0xffff)
2397 return 32;
2398
2399 return 16;
2400}
2401
Johan Hedberg92da6092013-03-15 17:06:55 -05002402static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2403{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002404 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002405
2406 hci_dev_lock(hdev);
2407
2408 cmd = mgmt_pending_find(mgmt_op, hdev);
2409 if (!cmd)
2410 goto unlock;
2411
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002412 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2413 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002414
2415 mgmt_pending_remove(cmd);
2416
2417unlock:
2418 hci_dev_unlock(hdev);
2419}
2420
Marcel Holtmann1904a852015-01-11 13:50:44 -08002421static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002422{
2423 BT_DBG("status 0x%02x", status);
2424
2425 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2426}
2427
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002428static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002429{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002430 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002431 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002432 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002433 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002434 int err;
2435
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002436 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002437
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002438 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002439
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002440 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002441 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2442 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002443 goto failed;
2444 }
2445
Andre Guedes92c4c202012-06-07 19:05:44 -03002446 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447 if (!uuid) {
2448 err = -ENOMEM;
2449 goto failed;
2450 }
2451
2452 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002453 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002454 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002455
Johan Hedbergde66aa62013-01-27 00:31:27 +02002456 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002457
Johan Hedberg890ea892013-03-15 17:06:52 -05002458 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002459
Johan Hedberg890ea892013-03-15 17:06:52 -05002460 update_class(&req);
2461 update_eir(&req);
2462
Johan Hedberg92da6092013-03-15 17:06:55 -05002463 err = hci_req_run(&req, add_uuid_complete);
2464 if (err < 0) {
2465 if (err != -ENODATA)
2466 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002467
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002468 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2469 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002470 goto failed;
2471 }
2472
2473 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002474 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002475 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002476 goto failed;
2477 }
2478
2479 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480
2481failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002482 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002483 return err;
2484}
2485
Johan Hedberg24b78d02012-02-23 23:24:30 +02002486static bool enable_service_cache(struct hci_dev *hdev)
2487{
2488 if (!hdev_is_powered(hdev))
2489 return false;
2490
2491 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002492 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2493 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002494 return true;
2495 }
2496
2497 return false;
2498}
2499
Marcel Holtmann1904a852015-01-11 13:50:44 -08002500static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002501{
2502 BT_DBG("status 0x%02x", status);
2503
2504 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2505}
2506
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002507static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002508 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002509{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002510 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002511 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002512 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002513 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 -05002514 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002515 int err, found;
2516
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002517 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002518
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002519 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002521 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002522 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2523 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002524 goto unlock;
2525 }
2526
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002527 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002528 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002529
Johan Hedberg24b78d02012-02-23 23:24:30 +02002530 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002531 err = mgmt_cmd_complete(sk, hdev->id,
2532 MGMT_OP_REMOVE_UUID,
2533 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002534 goto unlock;
2535 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002536
Johan Hedberg9246a862012-02-23 21:33:16 +02002537 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002538 }
2539
2540 found = 0;
2541
Johan Hedberg056341c2013-01-27 00:31:30 +02002542 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002543 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2544 continue;
2545
2546 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002547 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002548 found++;
2549 }
2550
2551 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002552 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2553 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002554 goto unlock;
2555 }
2556
Johan Hedberg9246a862012-02-23 21:33:16 +02002557update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002558 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002559
Johan Hedberg890ea892013-03-15 17:06:52 -05002560 update_class(&req);
2561 update_eir(&req);
2562
Johan Hedberg92da6092013-03-15 17:06:55 -05002563 err = hci_req_run(&req, remove_uuid_complete);
2564 if (err < 0) {
2565 if (err != -ENODATA)
2566 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002567
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002568 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2569 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002570 goto unlock;
2571 }
2572
2573 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002574 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002575 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002576 goto unlock;
2577 }
2578
2579 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002580
2581unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002582 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002583 return err;
2584}
2585
Marcel Holtmann1904a852015-01-11 13:50:44 -08002586static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002587{
2588 BT_DBG("status 0x%02x", status);
2589
2590 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2591}
2592
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002593static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002594 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002595{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002596 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002597 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002598 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002599 int err;
2600
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002601 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002602
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002603 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002604 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2605 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002606
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002607 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002608
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002609 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002610 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2611 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002612 goto unlock;
2613 }
2614
2615 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002616 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2617 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002618 goto unlock;
2619 }
2620
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002621 hdev->major_class = cp->major;
2622 hdev->minor_class = cp->minor;
2623
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002624 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002625 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2626 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002627 goto unlock;
2628 }
2629
Johan Hedberg890ea892013-03-15 17:06:52 -05002630 hci_req_init(&req, hdev);
2631
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002632 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002633 hci_dev_unlock(hdev);
2634 cancel_delayed_work_sync(&hdev->service_cache);
2635 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002636 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002637 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002638
Johan Hedberg890ea892013-03-15 17:06:52 -05002639 update_class(&req);
2640
Johan Hedberg92da6092013-03-15 17:06:55 -05002641 err = hci_req_run(&req, set_class_complete);
2642 if (err < 0) {
2643 if (err != -ENODATA)
2644 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002645
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002646 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2647 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002648 goto unlock;
2649 }
2650
2651 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002652 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002653 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002654 goto unlock;
2655 }
2656
2657 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002658
Johan Hedbergb5235a62012-02-21 14:32:24 +02002659unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002660 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002661 return err;
2662}
2663
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002664static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002665 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002666{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002667 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002668 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2669 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002670 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002671 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002672 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002673
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002674 BT_DBG("request for %s", hdev->name);
2675
2676 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002677 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2678 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002679
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002680 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002681 if (key_count > max_key_count) {
2682 BT_ERR("load_link_keys: too big key_count value %u",
2683 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002684 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2685 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002686 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002687
Johan Hedberg86742e12011-11-07 23:13:38 +02002688 expected_len = sizeof(*cp) + key_count *
2689 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002690 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002691 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002692 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002693 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2694 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002695 }
2696
Johan Hedberg4ae14302013-01-20 14:27:13 +02002697 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002698 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2699 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002700
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002701 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002702 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002704 for (i = 0; i < key_count; i++) {
2705 struct mgmt_link_key_info *key = &cp->keys[i];
2706
Marcel Holtmann8e991132014-01-10 02:07:25 -08002707 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002708 return mgmt_cmd_status(sk, hdev->id,
2709 MGMT_OP_LOAD_LINK_KEYS,
2710 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002711 }
2712
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002713 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002714
2715 hci_link_keys_clear(hdev);
2716
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002717 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002718 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2719 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002720 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002721 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2722 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002723
2724 if (changed)
2725 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002727 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002728 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002729
Johan Hedberg58e92932014-06-24 14:00:26 +03002730 /* Always ignore debug keys and require a new pairing if
2731 * the user wants to use them.
2732 */
2733 if (key->type == HCI_LK_DEBUG_COMBINATION)
2734 continue;
2735
Johan Hedberg7652ff62014-06-24 13:15:49 +03002736 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2737 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002738 }
2739
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002740 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002741
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002742 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002743
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002744 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002745}
2746
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002747static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002748 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002749{
2750 struct mgmt_ev_device_unpaired ev;
2751
2752 bacpy(&ev.addr.bdaddr, bdaddr);
2753 ev.addr.type = addr_type;
2754
2755 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002757}
2758
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002759static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002760 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002761{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002762 struct mgmt_cp_unpair_device *cp = data;
2763 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002764 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002765 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002766 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002767 int err;
2768
Johan Hedberga8a1d192011-11-10 15:54:38 +02002769 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002770 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2771 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002772
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002773 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002774 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2775 MGMT_STATUS_INVALID_PARAMS,
2776 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002777
Johan Hedberg118da702013-01-20 14:27:20 +02002778 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002779 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2780 MGMT_STATUS_INVALID_PARAMS,
2781 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002782
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002783 hci_dev_lock(hdev);
2784
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002785 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002786 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2787 MGMT_STATUS_NOT_POWERED, &rp,
2788 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002789 goto unlock;
2790 }
2791
Johan Hedberge0b2b272014-02-18 17:14:31 +02002792 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002793 /* If disconnection is requested, then look up the
2794 * connection. If the remote device is connected, it
2795 * will be later used to terminate the link.
2796 *
2797 * Setting it to NULL explicitly will cause no
2798 * termination of the link.
2799 */
2800 if (cp->disconnect)
2801 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2802 &cp->addr.bdaddr);
2803 else
2804 conn = NULL;
2805
Johan Hedberg124f6e32012-02-09 13:50:12 +02002806 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002807 } else {
2808 u8 addr_type;
2809
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002810 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2811 &cp->addr.bdaddr);
2812 if (conn) {
2813 /* Defer clearing up the connection parameters
2814 * until closing to give a chance of keeping
2815 * them if a repairing happens.
2816 */
2817 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2818
2819 /* If disconnection is not requested, then
2820 * clear the connection variable so that the
2821 * link is not terminated.
2822 */
2823 if (!cp->disconnect)
2824 conn = NULL;
2825 }
2826
Johan Hedberge0b2b272014-02-18 17:14:31 +02002827 if (cp->addr.type == BDADDR_LE_PUBLIC)
2828 addr_type = ADDR_LE_DEV_PUBLIC;
2829 else
2830 addr_type = ADDR_LE_DEV_RANDOM;
2831
Johan Hedberga7ec7332014-02-18 17:14:35 +02002832 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2833
Johan Hedberge0b2b272014-02-18 17:14:31 +02002834 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2835 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002836
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002837 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002838 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2839 MGMT_STATUS_NOT_PAIRED, &rp,
2840 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002841 goto unlock;
2842 }
2843
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002844 /* If the connection variable is set, then termination of the
2845 * link is requested.
2846 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002847 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002848 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2849 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002850 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002851 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002852 }
2853
Johan Hedberg124f6e32012-02-09 13:50:12 +02002854 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002855 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002856 if (!cmd) {
2857 err = -ENOMEM;
2858 goto unlock;
2859 }
2860
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002861 cmd->cmd_complete = addr_cmd_complete;
2862
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002863 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002864 dc.reason = 0x13; /* Remote User Terminated Connection */
2865 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2866 if (err < 0)
2867 mgmt_pending_remove(cmd);
2868
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002869unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002870 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002871 return err;
2872}
2873
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002874static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002875 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002876{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002877 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002878 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002879 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002880 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002881 int err;
2882
2883 BT_DBG("");
2884
Johan Hedberg06a63b12013-01-20 14:27:21 +02002885 memset(&rp, 0, sizeof(rp));
2886 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2887 rp.addr.type = cp->addr.type;
2888
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002889 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002890 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2891 MGMT_STATUS_INVALID_PARAMS,
2892 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002893
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002894 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002895
2896 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002897 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2898 MGMT_STATUS_NOT_POWERED, &rp,
2899 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002900 goto failed;
2901 }
2902
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002903 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002904 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2905 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002906 goto failed;
2907 }
2908
Andre Guedes591f47f2012-04-24 21:02:49 -03002909 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002910 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2911 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002912 else
2913 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002914
Vishal Agarwalf9607272012-06-13 05:32:43 +05302915 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002916 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2917 MGMT_STATUS_NOT_CONNECTED, &rp,
2918 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002919 goto failed;
2920 }
2921
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002922 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002923 if (!cmd) {
2924 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002925 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002926 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002927
Johan Hedbergf5818c22014-12-05 13:36:02 +02002928 cmd->cmd_complete = generic_cmd_complete;
2929
Johan Hedberge3f2f922014-08-18 20:33:33 +03002930 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002931 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002932 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002933
2934failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002935 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002936 return err;
2937}
2938
Andre Guedes57c14772012-04-24 21:02:50 -03002939static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002940{
2941 switch (link_type) {
2942 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002943 switch (addr_type) {
2944 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002945 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002946
Johan Hedberg48264f02011-11-09 13:58:58 +02002947 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002948 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002949 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002950 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002951
Johan Hedberg4c659c32011-11-07 23:13:39 +02002952 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002953 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002954 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002955 }
2956}
2957
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002958static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2959 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002960{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002961 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002962 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002963 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002964 int err;
2965 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002966
2967 BT_DBG("");
2968
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002969 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002970
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002971 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002972 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2973 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002974 goto unlock;
2975 }
2976
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002977 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002978 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2979 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002980 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002981 }
2982
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002983 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002984 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002985 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002986 err = -ENOMEM;
2987 goto unlock;
2988 }
2989
Johan Hedberg2784eb42011-01-21 13:56:35 +02002990 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002991 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002992 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2993 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002994 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002995 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002996 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002997 continue;
2998 i++;
2999 }
3000
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003001 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003002
Johan Hedberg4c659c32011-11-07 23:13:39 +02003003 /* Recalculate length in case of filtered SCO connections, etc */
3004 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003005
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003006 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3007 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003008
Johan Hedberga38528f2011-01-22 06:46:43 +02003009 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003010
3011unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003012 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003013 return err;
3014}
3015
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003016static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003017 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003018{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003019 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003020 int err;
3021
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003022 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003023 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003024 if (!cmd)
3025 return -ENOMEM;
3026
Johan Hedbergd8457692012-02-17 14:24:57 +02003027 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003028 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003029 if (err < 0)
3030 mgmt_pending_remove(cmd);
3031
3032 return err;
3033}
3034
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003035static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003036 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003037{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003038 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003039 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003041 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003042 int err;
3043
3044 BT_DBG("");
3045
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003046 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003047
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003048 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003049 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3050 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003051 goto failed;
3052 }
3053
Johan Hedbergd8457692012-02-17 14:24:57 +02003054 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003055 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003056 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3057 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003058 goto failed;
3059 }
3060
3061 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003062 struct mgmt_cp_pin_code_neg_reply ncp;
3063
3064 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003065
3066 BT_ERR("PIN code is not 16 bytes long");
3067
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003068 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003069 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003070 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3071 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003072
3073 goto failed;
3074 }
3075
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003076 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003077 if (!cmd) {
3078 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003079 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003080 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003081
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003082 cmd->cmd_complete = addr_cmd_complete;
3083
Johan Hedbergd8457692012-02-17 14:24:57 +02003084 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003085 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003086 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003087
3088 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3089 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003090 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003091
3092failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003093 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003094 return err;
3095}
3096
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003097static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3098 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003099{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003100 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003101
3102 BT_DBG("");
3103
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003104 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003105 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3106 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003107
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003108 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003109
3110 hdev->io_capability = cp->io_capability;
3111
3112 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003113 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003114
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003115 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003116
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003117 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3118 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003119}
3120
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003121static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003122{
3123 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003124 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003125
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003126 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003127 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3128 continue;
3129
Johan Hedberge9a416b2011-02-19 12:05:56 -03003130 if (cmd->user_data != conn)
3131 continue;
3132
3133 return cmd;
3134 }
3135
3136 return NULL;
3137}
3138
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003139static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003140{
3141 struct mgmt_rp_pair_device rp;
3142 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003143 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003144
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003145 bacpy(&rp.addr.bdaddr, &conn->dst);
3146 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003147
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003148 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3149 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003150
3151 /* So we don't get further callbacks for this connection */
3152 conn->connect_cfm_cb = NULL;
3153 conn->security_cfm_cb = NULL;
3154 conn->disconn_cfm_cb = NULL;
3155
David Herrmann76a68ba2013-04-06 20:28:37 +02003156 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003157
3158 /* The device is paired so there is no need to remove
3159 * its connection parameters anymore.
3160 */
3161 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003162
3163 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003164
3165 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166}
3167
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003168void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3169{
3170 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003171 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003172
3173 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003174 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003175 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003176 mgmt_pending_remove(cmd);
3177 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003178}
3179
Johan Hedberge9a416b2011-02-19 12:05:56 -03003180static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3181{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003182 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003183
3184 BT_DBG("status %u", status);
3185
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003186 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003187 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003188 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003189 return;
3190 }
3191
3192 cmd->cmd_complete(cmd, mgmt_status(status));
3193 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003194}
3195
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003196static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303197{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003198 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303199
3200 BT_DBG("status %u", status);
3201
3202 if (!status)
3203 return;
3204
3205 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003206 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303207 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003208 return;
3209 }
3210
3211 cmd->cmd_complete(cmd, mgmt_status(status));
3212 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303213}
3214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003215static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003216 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003217{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003218 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003219 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003220 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003221 u8 sec_level, auth_type;
3222 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003223 int err;
3224
3225 BT_DBG("");
3226
Szymon Jancf950a30e2013-01-18 12:48:07 +01003227 memset(&rp, 0, sizeof(rp));
3228 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3229 rp.addr.type = cp->addr.type;
3230
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003231 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003232 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3233 MGMT_STATUS_INVALID_PARAMS,
3234 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003235
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003236 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003237 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3238 MGMT_STATUS_INVALID_PARAMS,
3239 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003240
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003241 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003242
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003243 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003244 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3245 MGMT_STATUS_NOT_POWERED, &rp,
3246 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003247 goto unlock;
3248 }
3249
Johan Hedberg55e76b32015-03-10 22:34:40 +02003250 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3251 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3252 MGMT_STATUS_ALREADY_PAIRED, &rp,
3253 sizeof(rp));
3254 goto unlock;
3255 }
3256
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003257 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003258 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003259
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003260 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003261 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3262 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003263 } else {
3264 u8 addr_type;
3265
3266 /* Convert from L2CAP channel address type to HCI address type
3267 */
3268 if (cp->addr.type == BDADDR_LE_PUBLIC)
3269 addr_type = ADDR_LE_DEV_PUBLIC;
3270 else
3271 addr_type = ADDR_LE_DEV_RANDOM;
3272
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003273 /* When pairing a new device, it is expected to remember
3274 * this device for future connections. Adding the connection
3275 * parameter information ahead of time allows tracking
3276 * of the slave preferred values and will speed up any
3277 * further connection establishment.
3278 *
3279 * If connection parameters already exist, then they
3280 * will be kept and this function does nothing.
3281 */
3282 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3283
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003284 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003285 sec_level, HCI_LE_CONN_TIMEOUT,
3286 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003287 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003288
Ville Tervo30e76272011-02-22 16:10:53 -03003289 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003290 int status;
3291
3292 if (PTR_ERR(conn) == -EBUSY)
3293 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003294 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3295 status = MGMT_STATUS_NOT_SUPPORTED;
3296 else if (PTR_ERR(conn) == -ECONNREFUSED)
3297 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003298 else
3299 status = MGMT_STATUS_CONNECT_FAILED;
3300
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003301 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3302 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003303 goto unlock;
3304 }
3305
3306 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003307 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003308 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3309 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003310 goto unlock;
3311 }
3312
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003313 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003314 if (!cmd) {
3315 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003316 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003317 goto unlock;
3318 }
3319
Johan Hedberg04ab2742014-12-05 13:36:04 +02003320 cmd->cmd_complete = pairing_complete;
3321
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003322 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003323 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003324 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003325 conn->security_cfm_cb = pairing_complete_cb;
3326 conn->disconn_cfm_cb = pairing_complete_cb;
3327 } else {
3328 conn->connect_cfm_cb = le_pairing_complete_cb;
3329 conn->security_cfm_cb = le_pairing_complete_cb;
3330 conn->disconn_cfm_cb = le_pairing_complete_cb;
3331 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003332
Johan Hedberge9a416b2011-02-19 12:05:56 -03003333 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003334 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003335
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003336 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003337 hci_conn_security(conn, sec_level, auth_type, true)) {
3338 cmd->cmd_complete(cmd, 0);
3339 mgmt_pending_remove(cmd);
3340 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003341
3342 err = 0;
3343
3344unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003345 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003346 return err;
3347}
3348
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003349static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3350 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003351{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003352 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003353 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003354 struct hci_conn *conn;
3355 int err;
3356
3357 BT_DBG("");
3358
Johan Hedberg28424702012-02-02 04:02:29 +02003359 hci_dev_lock(hdev);
3360
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003361 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003362 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3363 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003364 goto unlock;
3365 }
3366
Johan Hedberg28424702012-02-02 04:02:29 +02003367 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3368 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003369 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3370 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003371 goto unlock;
3372 }
3373
3374 conn = cmd->user_data;
3375
3376 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003377 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3378 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003379 goto unlock;
3380 }
3381
Johan Hedberga511b352014-12-11 21:45:45 +02003382 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3383 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003385 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3386 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003387unlock:
3388 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003389 return err;
3390}
3391
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003392static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003393 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003394 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003395{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003396 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003397 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003398 int err;
3399
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003400 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003401
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003402 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003403 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3404 MGMT_STATUS_NOT_POWERED, addr,
3405 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003406 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003407 }
3408
Johan Hedberg1707c602013-03-15 17:07:15 -05003409 if (addr->type == BDADDR_BREDR)
3410 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003411 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003412 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003413
Johan Hedberg272d90d2012-02-09 15:26:12 +02003414 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003415 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3416 MGMT_STATUS_NOT_CONNECTED, addr,
3417 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003418 goto done;
3419 }
3420
Johan Hedberg1707c602013-03-15 17:07:15 -05003421 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003422 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003423 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003424 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3425 MGMT_STATUS_SUCCESS, addr,
3426 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003427 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003428 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3429 MGMT_STATUS_FAILED, addr,
3430 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003431
Brian Gix47c15e22011-11-16 13:53:14 -08003432 goto done;
3433 }
3434
Johan Hedberg1707c602013-03-15 17:07:15 -05003435 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003436 if (!cmd) {
3437 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003438 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003439 }
3440
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003441 cmd->cmd_complete = addr_cmd_complete;
3442
Brian Gix0df4c182011-11-16 13:53:13 -08003443 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003444 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3445 struct hci_cp_user_passkey_reply cp;
3446
Johan Hedberg1707c602013-03-15 17:07:15 -05003447 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003448 cp.passkey = passkey;
3449 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3450 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003451 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3452 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003453
Johan Hedberga664b5b2011-02-19 12:06:02 -03003454 if (err < 0)
3455 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003456
Brian Gix0df4c182011-11-16 13:53:13 -08003457done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003458 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003459 return err;
3460}
3461
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303462static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3463 void *data, u16 len)
3464{
3465 struct mgmt_cp_pin_code_neg_reply *cp = data;
3466
3467 BT_DBG("");
3468
Johan Hedberg1707c602013-03-15 17:07:15 -05003469 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303470 MGMT_OP_PIN_CODE_NEG_REPLY,
3471 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3472}
3473
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003474static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3475 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003477 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003478
3479 BT_DBG("");
3480
3481 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003482 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3483 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003484
Johan Hedberg1707c602013-03-15 17:07:15 -05003485 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003486 MGMT_OP_USER_CONFIRM_REPLY,
3487 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003488}
3489
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003490static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003491 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003492{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003493 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003494
3495 BT_DBG("");
3496
Johan Hedberg1707c602013-03-15 17:07:15 -05003497 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003498 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3499 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003500}
3501
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3503 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003504{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003505 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003506
3507 BT_DBG("");
3508
Johan Hedberg1707c602013-03-15 17:07:15 -05003509 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003510 MGMT_OP_USER_PASSKEY_REPLY,
3511 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003512}
3513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003515 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003516{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003517 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003518
3519 BT_DBG("");
3520
Johan Hedberg1707c602013-03-15 17:07:15 -05003521 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003522 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3523 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003524}
3525
Johan Hedberg13928972013-03-15 17:07:00 -05003526static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003527{
Johan Hedberg13928972013-03-15 17:07:00 -05003528 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003529 struct hci_cp_write_local_name cp;
3530
Johan Hedberg13928972013-03-15 17:07:00 -05003531 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003532
Johan Hedberg890ea892013-03-15 17:06:52 -05003533 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003534}
3535
Marcel Holtmann1904a852015-01-11 13:50:44 -08003536static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003537{
3538 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003539 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003540
3541 BT_DBG("status 0x%02x", status);
3542
3543 hci_dev_lock(hdev);
3544
3545 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3546 if (!cmd)
3547 goto unlock;
3548
3549 cp = cmd->param;
3550
3551 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003552 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3553 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003554 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003555 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3556 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003557
3558 mgmt_pending_remove(cmd);
3559
3560unlock:
3561 hci_dev_unlock(hdev);
3562}
3563
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003564static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003565 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003566{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003567 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003568 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003569 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003570 int err;
3571
3572 BT_DBG("");
3573
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003574 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003575
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003576 /* If the old values are the same as the new ones just return a
3577 * direct command complete event.
3578 */
3579 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3580 !memcmp(hdev->short_name, cp->short_name,
3581 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003582 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3583 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003584 goto failed;
3585 }
3586
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003587 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003588
Johan Hedbergb5235a62012-02-21 14:32:24 +02003589 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003590 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003591
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003592 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3593 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003594 if (err < 0)
3595 goto failed;
3596
3597 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003598 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003599
Johan Hedbergb5235a62012-02-21 14:32:24 +02003600 goto failed;
3601 }
3602
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003603 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003604 if (!cmd) {
3605 err = -ENOMEM;
3606 goto failed;
3607 }
3608
Johan Hedberg13928972013-03-15 17:07:00 -05003609 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3610
Johan Hedberg890ea892013-03-15 17:06:52 -05003611 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003612
3613 if (lmp_bredr_capable(hdev)) {
3614 update_name(&req);
3615 update_eir(&req);
3616 }
3617
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003618 /* The name is stored in the scan response data and so
3619 * no need to udpate the advertising data here.
3620 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003621 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003622 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003623
Johan Hedberg13928972013-03-15 17:07:00 -05003624 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003625 if (err < 0)
3626 mgmt_pending_remove(cmd);
3627
3628failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003629 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003630 return err;
3631}
3632
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003633static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003634 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003635{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003636 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003637 int err;
3638
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003639 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003640
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003641 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003642
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003643 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003644 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3645 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003646 goto unlock;
3647 }
3648
Andre Guedes9a1a1992012-07-24 15:03:48 -03003649 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003650 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3651 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003652 goto unlock;
3653 }
3654
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003655 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003656 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3657 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003658 goto unlock;
3659 }
3660
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003661 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003662 if (!cmd) {
3663 err = -ENOMEM;
3664 goto unlock;
3665 }
3666
Johan Hedberg710f11c2014-05-26 11:21:22 +03003667 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003668 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3669 0, NULL);
3670 else
3671 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3672
Szymon Jancc35938b2011-03-22 13:12:21 +01003673 if (err < 0)
3674 mgmt_pending_remove(cmd);
3675
3676unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003677 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003678 return err;
3679}
3680
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003681static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003682 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003683{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003684 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003685 int err;
3686
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003687 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003688
Johan Hedberg5d57e792015-01-23 10:10:38 +02003689 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003690 return mgmt_cmd_complete(sk, hdev->id,
3691 MGMT_OP_ADD_REMOTE_OOB_DATA,
3692 MGMT_STATUS_INVALID_PARAMS,
3693 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003694
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003695 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003696
Marcel Holtmannec109112014-01-10 02:07:30 -08003697 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3698 struct mgmt_cp_add_remote_oob_data *cp = data;
3699 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003700
Johan Hedbergc19a4952014-11-17 20:52:19 +02003701 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003702 err = mgmt_cmd_complete(sk, hdev->id,
3703 MGMT_OP_ADD_REMOTE_OOB_DATA,
3704 MGMT_STATUS_INVALID_PARAMS,
3705 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003706 goto unlock;
3707 }
3708
Marcel Holtmannec109112014-01-10 02:07:30 -08003709 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003710 cp->addr.type, cp->hash,
3711 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003712 if (err < 0)
3713 status = MGMT_STATUS_FAILED;
3714 else
3715 status = MGMT_STATUS_SUCCESS;
3716
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003717 err = mgmt_cmd_complete(sk, hdev->id,
3718 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3719 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003720 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3721 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003722 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003723 u8 status;
3724
Johan Hedberg86df9202014-10-26 20:52:27 +01003725 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003726 /* Enforce zero-valued 192-bit parameters as
3727 * long as legacy SMP OOB isn't implemented.
3728 */
3729 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3730 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003731 err = mgmt_cmd_complete(sk, hdev->id,
3732 MGMT_OP_ADD_REMOTE_OOB_DATA,
3733 MGMT_STATUS_INVALID_PARAMS,
3734 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003735 goto unlock;
3736 }
3737
Johan Hedberg86df9202014-10-26 20:52:27 +01003738 rand192 = NULL;
3739 hash192 = NULL;
3740 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003741 /* In case one of the P-192 values is set to zero,
3742 * then just disable OOB data for P-192.
3743 */
3744 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3745 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3746 rand192 = NULL;
3747 hash192 = NULL;
3748 } else {
3749 rand192 = cp->rand192;
3750 hash192 = cp->hash192;
3751 }
3752 }
3753
3754 /* In case one of the P-256 values is set to zero, then just
3755 * disable OOB data for P-256.
3756 */
3757 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3758 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3759 rand256 = NULL;
3760 hash256 = NULL;
3761 } else {
3762 rand256 = cp->rand256;
3763 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003764 }
3765
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003766 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003767 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003768 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003769 if (err < 0)
3770 status = MGMT_STATUS_FAILED;
3771 else
3772 status = MGMT_STATUS_SUCCESS;
3773
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003774 err = mgmt_cmd_complete(sk, hdev->id,
3775 MGMT_OP_ADD_REMOTE_OOB_DATA,
3776 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003777 } else {
3778 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003779 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3780 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003781 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003782
Johan Hedbergc19a4952014-11-17 20:52:19 +02003783unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003784 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003785 return err;
3786}
3787
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003788static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003789 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003790{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003791 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003792 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003793 int err;
3794
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003795 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003796
Johan Hedbergc19a4952014-11-17 20:52:19 +02003797 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003798 return mgmt_cmd_complete(sk, hdev->id,
3799 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3800 MGMT_STATUS_INVALID_PARAMS,
3801 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003802
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003803 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003804
Johan Hedbergeedbd582014-11-15 09:34:23 +02003805 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3806 hci_remote_oob_data_clear(hdev);
3807 status = MGMT_STATUS_SUCCESS;
3808 goto done;
3809 }
3810
Johan Hedberg6928a922014-10-26 20:46:09 +01003811 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003812 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003813 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003814 else
Szymon Janca6785be2012-12-13 15:11:21 +01003815 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003816
Johan Hedbergeedbd582014-11-15 09:34:23 +02003817done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003818 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3819 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003820
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003821 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003822 return err;
3823}
3824
Marcel Holtmann80190442014-12-04 11:36:36 +01003825static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003826{
Marcel Holtmann80190442014-12-04 11:36:36 +01003827 struct hci_dev *hdev = req->hdev;
3828 struct hci_cp_le_set_scan_param param_cp;
3829 struct hci_cp_le_set_scan_enable enable_cp;
3830 struct hci_cp_inquiry inq_cp;
3831 /* General inquiry access code (GIAC) */
3832 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3833 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003834 int err;
3835
Marcel Holtmann80190442014-12-04 11:36:36 +01003836 switch (hdev->discovery.type) {
3837 case DISCOV_TYPE_BREDR:
3838 *status = mgmt_bredr_support(hdev);
3839 if (*status)
3840 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003841
Marcel Holtmann80190442014-12-04 11:36:36 +01003842 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3843 *status = MGMT_STATUS_BUSY;
3844 return false;
3845 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003846
Marcel Holtmann80190442014-12-04 11:36:36 +01003847 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003848
Marcel Holtmann80190442014-12-04 11:36:36 +01003849 memset(&inq_cp, 0, sizeof(inq_cp));
3850 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3851 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3852 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3853 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003854
Marcel Holtmann80190442014-12-04 11:36:36 +01003855 case DISCOV_TYPE_LE:
3856 case DISCOV_TYPE_INTERLEAVED:
3857 *status = mgmt_le_support(hdev);
3858 if (*status)
3859 return false;
3860
3861 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003862 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003863 *status = MGMT_STATUS_NOT_SUPPORTED;
3864 return false;
3865 }
3866
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003867 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003868 /* Don't let discovery abort an outgoing
3869 * connection attempt that's using directed
3870 * advertising.
3871 */
3872 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3873 BT_CONNECT)) {
3874 *status = MGMT_STATUS_REJECTED;
3875 return false;
3876 }
3877
3878 disable_advertising(req);
3879 }
3880
3881 /* If controller is scanning, it means the background scanning
3882 * is running. Thus, we should temporarily stop it in order to
3883 * set the discovery scanning parameters.
3884 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003885 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
Marcel Holtmann80190442014-12-04 11:36:36 +01003886 hci_req_add_le_scan_disable(req);
3887
3888 memset(&param_cp, 0, sizeof(param_cp));
3889
3890 /* All active scans will be done with either a resolvable
3891 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003892 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003893 */
3894 err = hci_update_random_address(req, true, &own_addr_type);
3895 if (err < 0) {
3896 *status = MGMT_STATUS_FAILED;
3897 return false;
3898 }
3899
3900 param_cp.type = LE_SCAN_ACTIVE;
3901 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3902 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3903 param_cp.own_address_type = own_addr_type;
3904 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3905 &param_cp);
3906
3907 memset(&enable_cp, 0, sizeof(enable_cp));
3908 enable_cp.enable = LE_SCAN_ENABLE;
3909 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3910 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3911 &enable_cp);
3912 break;
3913
3914 default:
3915 *status = MGMT_STATUS_INVALID_PARAMS;
3916 return false;
3917 }
3918
3919 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003920}
3921
Marcel Holtmann1904a852015-01-11 13:50:44 -08003922static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3923 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003924{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003925 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003926 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003927
Andre Guedes7c307722013-04-30 15:29:28 -03003928 BT_DBG("status %d", status);
3929
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003930 hci_dev_lock(hdev);
3931
3932 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003933 if (!cmd)
3934 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3935
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003936 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003937 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003938 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003939 }
3940
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003941 if (status) {
3942 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3943 goto unlock;
3944 }
3945
Andre Guedes7c307722013-04-30 15:29:28 -03003946 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003947
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003948 /* If the scan involves LE scan, pick proper timeout to schedule
3949 * hdev->le_scan_disable that will stop it.
3950 */
Andre Guedes7c307722013-04-30 15:29:28 -03003951 switch (hdev->discovery.type) {
3952 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003953 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003954 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003955 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003956 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003957 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003958 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003959 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003960 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003961 default:
3962 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003963 timeout = 0;
3964 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003965 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003966
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003967 if (timeout) {
3968 /* When service discovery is used and the controller has
3969 * a strict duplicate filter, it is important to remember
3970 * the start and duration of the scan. This is required
3971 * for restarting scanning during the discovery phase.
3972 */
3973 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3974 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003975 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003976 hdev->discovery.scan_start = jiffies;
3977 hdev->discovery.scan_duration = timeout;
3978 }
3979
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003980 queue_delayed_work(hdev->workqueue,
3981 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003982 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003983
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003984unlock:
3985 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003986}
3987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003988static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003989 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003990{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003991 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003992 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003993 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003994 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003995 int err;
3996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003997 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003998
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003999 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004000
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004001 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004002 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4003 MGMT_STATUS_NOT_POWERED,
4004 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004005 goto failed;
4006 }
4007
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004008 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004009 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004010 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4011 MGMT_STATUS_BUSY, &cp->type,
4012 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004013 goto failed;
4014 }
4015
Johan Hedberg2922a942014-12-05 13:36:06 +02004016 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004017 if (!cmd) {
4018 err = -ENOMEM;
4019 goto failed;
4020 }
4021
Johan Hedberg2922a942014-12-05 13:36:06 +02004022 cmd->cmd_complete = generic_cmd_complete;
4023
Marcel Holtmann22078802014-12-05 11:45:22 +01004024 /* Clear the discovery filter first to free any previously
4025 * allocated memory for the UUID list.
4026 */
4027 hci_discovery_filter_clear(hdev);
4028
Andre Guedes4aab14e2012-02-17 20:39:36 -03004029 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004030 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004031
Andre Guedes7c307722013-04-30 15:29:28 -03004032 hci_req_init(&req, hdev);
4033
Marcel Holtmann80190442014-12-04 11:36:36 +01004034 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004035 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4036 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004037 mgmt_pending_remove(cmd);
4038 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004039 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004040
Andre Guedes7c307722013-04-30 15:29:28 -03004041 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004042 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004043 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004044 goto failed;
4045 }
4046
4047 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004048
4049failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004050 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004051 return err;
4052}
4053
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004054static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4055 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004056{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004057 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4058 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004059}
4060
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004061static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4062 void *data, u16 len)
4063{
4064 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004065 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004066 struct hci_request req;
4067 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4068 u16 uuid_count, expected_len;
4069 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004070 int err;
4071
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004072 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004073
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004074 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004075
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004076 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004077 err = mgmt_cmd_complete(sk, hdev->id,
4078 MGMT_OP_START_SERVICE_DISCOVERY,
4079 MGMT_STATUS_NOT_POWERED,
4080 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004081 goto failed;
4082 }
4083
4084 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004085 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004086 err = mgmt_cmd_complete(sk, hdev->id,
4087 MGMT_OP_START_SERVICE_DISCOVERY,
4088 MGMT_STATUS_BUSY, &cp->type,
4089 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004090 goto failed;
4091 }
4092
4093 uuid_count = __le16_to_cpu(cp->uuid_count);
4094 if (uuid_count > max_uuid_count) {
4095 BT_ERR("service_discovery: too big uuid_count value %u",
4096 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004097 err = mgmt_cmd_complete(sk, hdev->id,
4098 MGMT_OP_START_SERVICE_DISCOVERY,
4099 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4100 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004101 goto failed;
4102 }
4103
4104 expected_len = sizeof(*cp) + uuid_count * 16;
4105 if (expected_len != len) {
4106 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4107 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004108 err = mgmt_cmd_complete(sk, hdev->id,
4109 MGMT_OP_START_SERVICE_DISCOVERY,
4110 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4111 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004112 goto failed;
4113 }
4114
4115 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004116 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004117 if (!cmd) {
4118 err = -ENOMEM;
4119 goto failed;
4120 }
4121
Johan Hedberg2922a942014-12-05 13:36:06 +02004122 cmd->cmd_complete = service_discovery_cmd_complete;
4123
Marcel Holtmann22078802014-12-05 11:45:22 +01004124 /* Clear the discovery filter first to free any previously
4125 * allocated memory for the UUID list.
4126 */
4127 hci_discovery_filter_clear(hdev);
4128
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004129 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004130 hdev->discovery.type = cp->type;
4131 hdev->discovery.rssi = cp->rssi;
4132 hdev->discovery.uuid_count = uuid_count;
4133
4134 if (uuid_count > 0) {
4135 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4136 GFP_KERNEL);
4137 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004138 err = mgmt_cmd_complete(sk, hdev->id,
4139 MGMT_OP_START_SERVICE_DISCOVERY,
4140 MGMT_STATUS_FAILED,
4141 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004142 mgmt_pending_remove(cmd);
4143 goto failed;
4144 }
4145 }
4146
4147 hci_req_init(&req, hdev);
4148
4149 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004150 err = mgmt_cmd_complete(sk, hdev->id,
4151 MGMT_OP_START_SERVICE_DISCOVERY,
4152 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004153 mgmt_pending_remove(cmd);
4154 goto failed;
4155 }
4156
4157 err = hci_req_run(&req, start_discovery_complete);
4158 if (err < 0) {
4159 mgmt_pending_remove(cmd);
4160 goto failed;
4161 }
4162
4163 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4164
4165failed:
4166 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004167 return err;
4168}
4169
Marcel Holtmann1904a852015-01-11 13:50:44 -08004170static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004171{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004172 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004173
Andre Guedes0e05bba2013-04-30 15:29:33 -03004174 BT_DBG("status %d", status);
4175
4176 hci_dev_lock(hdev);
4177
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004178 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4179 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004180 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004181 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004182 }
4183
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004184 if (!status)
4185 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004186
Andre Guedes0e05bba2013-04-30 15:29:33 -03004187 hci_dev_unlock(hdev);
4188}
4189
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004190static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004191 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004192{
Johan Hedbergd9306502012-02-20 23:25:18 +02004193 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004194 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004195 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004196 int err;
4197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004198 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004199
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004200 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004201
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004202 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004203 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4204 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4205 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004206 goto unlock;
4207 }
4208
4209 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004210 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4211 MGMT_STATUS_INVALID_PARAMS,
4212 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004213 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004214 }
4215
Johan Hedberg2922a942014-12-05 13:36:06 +02004216 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004217 if (!cmd) {
4218 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004219 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004220 }
4221
Johan Hedberg2922a942014-12-05 13:36:06 +02004222 cmd->cmd_complete = generic_cmd_complete;
4223
Andre Guedes0e05bba2013-04-30 15:29:33 -03004224 hci_req_init(&req, hdev);
4225
Johan Hedberg21a60d32014-06-10 14:05:58 +03004226 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004227
Johan Hedberg21a60d32014-06-10 14:05:58 +03004228 err = hci_req_run(&req, stop_discovery_complete);
4229 if (!err) {
4230 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004231 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004232 }
4233
Johan Hedberg21a60d32014-06-10 14:05:58 +03004234 mgmt_pending_remove(cmd);
4235
4236 /* If no HCI commands were sent we're done */
4237 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004238 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4239 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004240 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4241 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004242
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004243unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004244 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004245 return err;
4246}
4247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004248static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004249 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004250{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004251 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004252 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004253 int err;
4254
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004255 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004256
Johan Hedberg561aafb2012-01-04 13:31:59 +02004257 hci_dev_lock(hdev);
4258
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004259 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004260 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4261 MGMT_STATUS_FAILED, &cp->addr,
4262 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004263 goto failed;
4264 }
4265
Johan Hedberga198e7b2012-02-17 14:27:06 +02004266 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004267 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004268 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4269 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4270 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004271 goto failed;
4272 }
4273
4274 if (cp->name_known) {
4275 e->name_state = NAME_KNOWN;
4276 list_del(&e->list);
4277 } else {
4278 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004279 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004280 }
4281
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004282 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4283 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004284
4285failed:
4286 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004287 return err;
4288}
4289
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004290static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004291 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004292{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004293 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004294 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004295 int err;
4296
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004297 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004298
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004299 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004300 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4301 MGMT_STATUS_INVALID_PARAMS,
4302 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004303
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004304 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004305
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004306 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4307 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004308 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004309 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004310 goto done;
4311 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004312
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004313 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4314 sk);
4315 status = MGMT_STATUS_SUCCESS;
4316
4317done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004318 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4319 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004320
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004321 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004322
4323 return err;
4324}
4325
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004326static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004327 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004328{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004329 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004330 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004331 int err;
4332
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004333 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004334
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004335 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004336 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4337 MGMT_STATUS_INVALID_PARAMS,
4338 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004339
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004340 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004341
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004342 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4343 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004344 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004345 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004346 goto done;
4347 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004348
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004349 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4350 sk);
4351 status = MGMT_STATUS_SUCCESS;
4352
4353done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004354 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4355 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004356
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004357 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004358
4359 return err;
4360}
4361
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004362static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4363 u16 len)
4364{
4365 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004366 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004367 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004368 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004369
4370 BT_DBG("%s", hdev->name);
4371
Szymon Jancc72d4b82012-03-16 16:02:57 +01004372 source = __le16_to_cpu(cp->source);
4373
4374 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004375 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4376 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004377
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004378 hci_dev_lock(hdev);
4379
Szymon Jancc72d4b82012-03-16 16:02:57 +01004380 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004381 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4382 hdev->devid_product = __le16_to_cpu(cp->product);
4383 hdev->devid_version = __le16_to_cpu(cp->version);
4384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004385 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4386 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004387
Johan Hedberg890ea892013-03-15 17:06:52 -05004388 hci_req_init(&req, hdev);
4389 update_eir(&req);
4390 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004391
4392 hci_dev_unlock(hdev);
4393
4394 return err;
4395}
4396
Marcel Holtmann1904a852015-01-11 13:50:44 -08004397static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4398 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004399{
4400 struct cmd_lookup match = { NULL, hdev };
4401
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304402 hci_dev_lock(hdev);
4403
Johan Hedberg4375f102013-09-25 13:26:10 +03004404 if (status) {
4405 u8 mgmt_err = mgmt_status(status);
4406
4407 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4408 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304409 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004410 }
4411
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004412 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedbergc93bd152014-07-08 15:07:48 +03004413 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4414 else
4415 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4416
Johan Hedberg4375f102013-09-25 13:26:10 +03004417 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4418 &match);
4419
4420 new_settings(hdev, match.sk);
4421
4422 if (match.sk)
4423 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304424
4425unlock:
4426 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004427}
4428
Marcel Holtmann21b51872013-10-10 09:47:53 -07004429static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4430 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004431{
4432 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004433 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004434 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004435 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004436 int err;
4437
4438 BT_DBG("request for %s", hdev->name);
4439
Johan Hedberge6fe7982013-10-02 15:45:22 +03004440 status = mgmt_le_support(hdev);
4441 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004442 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4443 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004444
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004445 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004446 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4447 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004448
4449 hci_dev_lock(hdev);
4450
4451 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004452
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004453 /* The following conditions are ones which mean that we should
4454 * not do any HCI communication but directly send a mgmt
4455 * response to user space (after toggling the flag if
4456 * necessary).
4457 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004458 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004459 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4460 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004461 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004462 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004463 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004464 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004465
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004466 if (cp->val) {
4467 changed = !test_and_set_bit(HCI_ADVERTISING,
4468 &hdev->dev_flags);
4469 if (cp->val == 0x02)
4470 set_bit(HCI_ADVERTISING_CONNECTABLE,
4471 &hdev->dev_flags);
4472 else
4473 clear_bit(HCI_ADVERTISING_CONNECTABLE,
4474 &hdev->dev_flags);
4475 } else {
4476 changed = test_and_clear_bit(HCI_ADVERTISING,
4477 &hdev->dev_flags);
4478 clear_bit(HCI_ADVERTISING_CONNECTABLE,
4479 &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004480 }
4481
4482 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4483 if (err < 0)
4484 goto unlock;
4485
4486 if (changed)
4487 err = new_settings(hdev, sk);
4488
4489 goto unlock;
4490 }
4491
4492 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4493 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004494 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4495 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004496 goto unlock;
4497 }
4498
4499 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4500 if (!cmd) {
4501 err = -ENOMEM;
4502 goto unlock;
4503 }
4504
4505 hci_req_init(&req, hdev);
4506
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004507 if (cp->val == 0x02)
4508 set_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags);
4509 else
4510 clear_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags);
4511
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004512 if (val)
4513 enable_advertising(&req);
4514 else
4515 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004516
4517 err = hci_req_run(&req, set_advertising_complete);
4518 if (err < 0)
4519 mgmt_pending_remove(cmd);
4520
4521unlock:
4522 hci_dev_unlock(hdev);
4523 return err;
4524}
4525
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004526static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4527 void *data, u16 len)
4528{
4529 struct mgmt_cp_set_static_address *cp = data;
4530 int err;
4531
4532 BT_DBG("%s", hdev->name);
4533
Marcel Holtmann62af4442013-10-02 22:10:32 -07004534 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004535 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4536 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004537
4538 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004539 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4540 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004541
4542 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4543 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004544 return mgmt_cmd_status(sk, hdev->id,
4545 MGMT_OP_SET_STATIC_ADDRESS,
4546 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004547
4548 /* Two most significant bits shall be set */
4549 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004550 return mgmt_cmd_status(sk, hdev->id,
4551 MGMT_OP_SET_STATIC_ADDRESS,
4552 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004553 }
4554
4555 hci_dev_lock(hdev);
4556
4557 bacpy(&hdev->static_addr, &cp->bdaddr);
4558
Marcel Holtmann93690c22015-03-06 10:11:21 -08004559 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4560 if (err < 0)
4561 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004562
Marcel Holtmann93690c22015-03-06 10:11:21 -08004563 err = new_settings(hdev, sk);
4564
4565unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004566 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004567 return err;
4568}
4569
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004570static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4571 void *data, u16 len)
4572{
4573 struct mgmt_cp_set_scan_params *cp = data;
4574 __u16 interval, window;
4575 int err;
4576
4577 BT_DBG("%s", hdev->name);
4578
4579 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004580 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4581 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004582
4583 interval = __le16_to_cpu(cp->interval);
4584
4585 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004586 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4587 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004588
4589 window = __le16_to_cpu(cp->window);
4590
4591 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004592 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4593 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004594
Marcel Holtmann899e1072013-10-14 09:55:32 -07004595 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004596 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4597 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004598
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004599 hci_dev_lock(hdev);
4600
4601 hdev->le_scan_interval = interval;
4602 hdev->le_scan_window = window;
4603
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004604 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4605 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004606
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004607 /* If background scan is running, restart it so new parameters are
4608 * loaded.
4609 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004610 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004611 hdev->discovery.state == DISCOVERY_STOPPED) {
4612 struct hci_request req;
4613
4614 hci_req_init(&req, hdev);
4615
4616 hci_req_add_le_scan_disable(&req);
4617 hci_req_add_le_passive_scan(&req);
4618
4619 hci_req_run(&req, NULL);
4620 }
4621
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004622 hci_dev_unlock(hdev);
4623
4624 return err;
4625}
4626
Marcel Holtmann1904a852015-01-11 13:50:44 -08004627static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4628 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004629{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004630 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004631
4632 BT_DBG("status 0x%02x", status);
4633
4634 hci_dev_lock(hdev);
4635
4636 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4637 if (!cmd)
4638 goto unlock;
4639
4640 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004641 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4642 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004643 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004644 struct mgmt_mode *cp = cmd->param;
4645
4646 if (cp->val)
4647 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4648 else
4649 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4650
Johan Hedberg33e38b32013-03-15 17:07:05 -05004651 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4652 new_settings(hdev, cmd->sk);
4653 }
4654
4655 mgmt_pending_remove(cmd);
4656
4657unlock:
4658 hci_dev_unlock(hdev);
4659}
4660
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004661static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004662 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004663{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004664 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004665 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004666 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004667 int err;
4668
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004669 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004670
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004671 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004672 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004673 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4674 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004675
Johan Hedberga7e80f22013-01-09 16:05:19 +02004676 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004677 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4678 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004679
Antti Julkuf6422ec2011-06-22 13:11:56 +03004680 hci_dev_lock(hdev);
4681
Johan Hedberg05cbf292013-03-15 17:07:07 -05004682 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004683 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4684 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004685 goto unlock;
4686 }
4687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004688 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004689 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4690 hdev);
4691 goto unlock;
4692 }
4693
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004694 if (!hdev_is_powered(hdev)) {
4695 change_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4696 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4697 hdev);
4698 new_settings(hdev, sk);
4699 goto unlock;
4700 }
4701
Johan Hedberg33e38b32013-03-15 17:07:05 -05004702 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4703 data, len);
4704 if (!cmd) {
4705 err = -ENOMEM;
4706 goto unlock;
4707 }
4708
4709 hci_req_init(&req, hdev);
4710
Johan Hedberg406d7802013-03-15 17:07:09 -05004711 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004712
4713 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004714 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004715 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4716 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004717 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004718 }
4719
Johan Hedberg33e38b32013-03-15 17:07:05 -05004720unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004721 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004722
Antti Julkuf6422ec2011-06-22 13:11:56 +03004723 return err;
4724}
4725
Marcel Holtmann1904a852015-01-11 13:50:44 -08004726static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004727{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004728 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004729
4730 BT_DBG("status 0x%02x", status);
4731
4732 hci_dev_lock(hdev);
4733
4734 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4735 if (!cmd)
4736 goto unlock;
4737
4738 if (status) {
4739 u8 mgmt_err = mgmt_status(status);
4740
4741 /* We need to restore the flag if related HCI commands
4742 * failed.
4743 */
4744 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4745
Johan Hedberga69e8372015-03-06 21:08:53 +02004746 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004747 } else {
4748 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4749 new_settings(hdev, cmd->sk);
4750 }
4751
4752 mgmt_pending_remove(cmd);
4753
4754unlock:
4755 hci_dev_unlock(hdev);
4756}
4757
4758static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4759{
4760 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004761 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004762 struct hci_request req;
4763 int err;
4764
4765 BT_DBG("request for %s", hdev->name);
4766
4767 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004768 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4769 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004770
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004771 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004772 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4773 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004774
4775 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004776 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4777 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004778
4779 hci_dev_lock(hdev);
4780
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004781 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004782 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4783 goto unlock;
4784 }
4785
4786 if (!hdev_is_powered(hdev)) {
4787 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004788 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4789 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4790 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4791 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4792 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4793 }
4794
4795 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4796
4797 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4798 if (err < 0)
4799 goto unlock;
4800
4801 err = new_settings(hdev, sk);
4802 goto unlock;
4803 }
4804
4805 /* Reject disabling when powered on */
4806 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004807 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4808 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004809 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004810 } else {
4811 /* When configuring a dual-mode controller to operate
4812 * with LE only and using a static address, then switching
4813 * BR/EDR back on is not allowed.
4814 *
4815 * Dual-mode controllers shall operate with the public
4816 * address as its identity address for BR/EDR and LE. So
4817 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004818 *
4819 * The same restrictions applies when secure connections
4820 * has been enabled. For BR/EDR this is a controller feature
4821 * while for LE it is a host stack feature. This means that
4822 * switching BR/EDR back on when secure connections has been
4823 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004824 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004825 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004826 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004827 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004828 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4829 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004830 goto unlock;
4831 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004832 }
4833
4834 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004835 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4836 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004837 goto unlock;
4838 }
4839
4840 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4841 if (!cmd) {
4842 err = -ENOMEM;
4843 goto unlock;
4844 }
4845
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004846 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004847 * generates the correct flags.
4848 */
4849 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4850
4851 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004852
Johan Hedberg432df052014-08-01 11:13:31 +03004853 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004854 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004855
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004856 /* Since only the advertising data flags will change, there
4857 * is no need to update the scan response data.
4858 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004859 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004860
Johan Hedberg0663ca22013-10-02 13:43:14 +03004861 err = hci_req_run(&req, set_bredr_complete);
4862 if (err < 0)
4863 mgmt_pending_remove(cmd);
4864
4865unlock:
4866 hci_dev_unlock(hdev);
4867 return err;
4868}
4869
Johan Hedberga1443f52015-01-23 15:42:46 +02004870static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4871{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004872 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004873 struct mgmt_mode *cp;
4874
4875 BT_DBG("%s status %u", hdev->name, status);
4876
4877 hci_dev_lock(hdev);
4878
4879 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4880 if (!cmd)
4881 goto unlock;
4882
4883 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004884 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4885 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004886 goto remove;
4887 }
4888
4889 cp = cmd->param;
4890
4891 switch (cp->val) {
4892 case 0x00:
4893 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4894 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4895 break;
4896 case 0x01:
4897 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4898 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4899 break;
4900 case 0x02:
4901 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4902 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4903 break;
4904 }
4905
4906 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4907 new_settings(hdev, cmd->sk);
4908
4909remove:
4910 mgmt_pending_remove(cmd);
4911unlock:
4912 hci_dev_unlock(hdev);
4913}
4914
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004915static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4916 void *data, u16 len)
4917{
4918 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004919 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004920 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004921 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004922 int err;
4923
4924 BT_DBG("request for %s", hdev->name);
4925
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004926 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004927 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004928 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4929 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004930
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004931 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004932 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004933 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004934 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4935 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004936
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004937 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004938 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004939 MGMT_STATUS_INVALID_PARAMS);
4940
4941 hci_dev_lock(hdev);
4942
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004943 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004944 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004945 bool changed;
4946
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004947 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004948 changed = !test_and_set_bit(HCI_SC_ENABLED,
4949 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004950 if (cp->val == 0x02)
4951 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4952 else
4953 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4954 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004955 changed = test_and_clear_bit(HCI_SC_ENABLED,
4956 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004957 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4958 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004959
4960 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4961 if (err < 0)
4962 goto failed;
4963
4964 if (changed)
4965 err = new_settings(hdev, sk);
4966
4967 goto failed;
4968 }
4969
4970 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004971 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4972 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004973 goto failed;
4974 }
4975
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004976 val = !!cp->val;
4977
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004978 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
4979 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004980 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4981 goto failed;
4982 }
4983
4984 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4985 if (!cmd) {
4986 err = -ENOMEM;
4987 goto failed;
4988 }
4989
Johan Hedberga1443f52015-01-23 15:42:46 +02004990 hci_req_init(&req, hdev);
4991 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4992 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004993 if (err < 0) {
4994 mgmt_pending_remove(cmd);
4995 goto failed;
4996 }
4997
4998failed:
4999 hci_dev_unlock(hdev);
5000 return err;
5001}
5002
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005003static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5004 void *data, u16 len)
5005{
5006 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005007 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005008 int err;
5009
5010 BT_DBG("request for %s", hdev->name);
5011
Johan Hedbergb97109792014-06-24 14:00:28 +03005012 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005013 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5014 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005015
5016 hci_dev_lock(hdev);
5017
5018 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03005019 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
5020 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005021 else
Johan Hedberg0663b292014-06-24 13:15:50 +03005022 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
5023 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005024
Johan Hedbergb97109792014-06-24 14:00:28 +03005025 if (cp->val == 0x02)
5026 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
5027 &hdev->dev_flags);
5028 else
5029 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
5030 &hdev->dev_flags);
5031
5032 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005033 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005034 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5035 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5036 sizeof(mode), &mode);
5037 }
5038
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005039 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5040 if (err < 0)
5041 goto unlock;
5042
5043 if (changed)
5044 err = new_settings(hdev, sk);
5045
5046unlock:
5047 hci_dev_unlock(hdev);
5048 return err;
5049}
5050
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005051static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5052 u16 len)
5053{
5054 struct mgmt_cp_set_privacy *cp = cp_data;
5055 bool changed;
5056 int err;
5057
5058 BT_DBG("request for %s", hdev->name);
5059
5060 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005061 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5062 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005063
5064 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005065 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5066 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005067
5068 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005069 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5070 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005071
5072 hci_dev_lock(hdev);
5073
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005074 /* If user space supports this command it is also expected to
5075 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5076 */
5077 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5078
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005079 if (cp->privacy) {
5080 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5081 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5082 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5083 } else {
5084 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5085 memset(hdev->irk, 0, sizeof(hdev->irk));
5086 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5087 }
5088
5089 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5090 if (err < 0)
5091 goto unlock;
5092
5093 if (changed)
5094 err = new_settings(hdev, sk);
5095
5096unlock:
5097 hci_dev_unlock(hdev);
5098 return err;
5099}
5100
Johan Hedberg41edf162014-02-18 10:19:35 +02005101static bool irk_is_valid(struct mgmt_irk_info *irk)
5102{
5103 switch (irk->addr.type) {
5104 case BDADDR_LE_PUBLIC:
5105 return true;
5106
5107 case BDADDR_LE_RANDOM:
5108 /* Two most significant bits shall be set */
5109 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5110 return false;
5111 return true;
5112 }
5113
5114 return false;
5115}
5116
5117static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5118 u16 len)
5119{
5120 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005121 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5122 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005123 u16 irk_count, expected_len;
5124 int i, err;
5125
5126 BT_DBG("request for %s", hdev->name);
5127
5128 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005129 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5130 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005131
5132 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005133 if (irk_count > max_irk_count) {
5134 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005135 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5136 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005137 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005138
5139 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5140 if (expected_len != len) {
5141 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005142 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005143 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5144 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005145 }
5146
5147 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5148
5149 for (i = 0; i < irk_count; i++) {
5150 struct mgmt_irk_info *key = &cp->irks[i];
5151
5152 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005153 return mgmt_cmd_status(sk, hdev->id,
5154 MGMT_OP_LOAD_IRKS,
5155 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005156 }
5157
5158 hci_dev_lock(hdev);
5159
5160 hci_smp_irks_clear(hdev);
5161
5162 for (i = 0; i < irk_count; i++) {
5163 struct mgmt_irk_info *irk = &cp->irks[i];
5164 u8 addr_type;
5165
5166 if (irk->addr.type == BDADDR_LE_PUBLIC)
5167 addr_type = ADDR_LE_DEV_PUBLIC;
5168 else
5169 addr_type = ADDR_LE_DEV_RANDOM;
5170
5171 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5172 BDADDR_ANY);
5173 }
5174
5175 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5176
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005177 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005178
5179 hci_dev_unlock(hdev);
5180
5181 return err;
5182}
5183
Johan Hedberg3f706b72013-01-20 14:27:16 +02005184static bool ltk_is_valid(struct mgmt_ltk_info *key)
5185{
5186 if (key->master != 0x00 && key->master != 0x01)
5187 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005188
5189 switch (key->addr.type) {
5190 case BDADDR_LE_PUBLIC:
5191 return true;
5192
5193 case BDADDR_LE_RANDOM:
5194 /* Two most significant bits shall be set */
5195 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5196 return false;
5197 return true;
5198 }
5199
5200 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005201}
5202
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005203static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005204 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005205{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005206 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005207 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5208 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005209 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005210 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005211
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005212 BT_DBG("request for %s", hdev->name);
5213
5214 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005215 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5216 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005217
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005218 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005219 if (key_count > max_key_count) {
5220 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005221 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5222 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005223 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005224
5225 expected_len = sizeof(*cp) + key_count *
5226 sizeof(struct mgmt_ltk_info);
5227 if (expected_len != len) {
5228 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005229 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005230 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5231 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005232 }
5233
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005234 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005235
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005236 for (i = 0; i < key_count; i++) {
5237 struct mgmt_ltk_info *key = &cp->keys[i];
5238
Johan Hedberg3f706b72013-01-20 14:27:16 +02005239 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005240 return mgmt_cmd_status(sk, hdev->id,
5241 MGMT_OP_LOAD_LONG_TERM_KEYS,
5242 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005243 }
5244
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005245 hci_dev_lock(hdev);
5246
5247 hci_smp_ltks_clear(hdev);
5248
5249 for (i = 0; i < key_count; i++) {
5250 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005251 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005252
5253 if (key->addr.type == BDADDR_LE_PUBLIC)
5254 addr_type = ADDR_LE_DEV_PUBLIC;
5255 else
5256 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005257
Johan Hedberg61b43352014-05-29 19:36:53 +03005258 switch (key->type) {
5259 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005260 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005261 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005262 break;
5263 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005264 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005265 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005266 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005267 case MGMT_LTK_P256_UNAUTH:
5268 authenticated = 0x00;
5269 type = SMP_LTK_P256;
5270 break;
5271 case MGMT_LTK_P256_AUTH:
5272 authenticated = 0x01;
5273 type = SMP_LTK_P256;
5274 break;
5275 case MGMT_LTK_P256_DEBUG:
5276 authenticated = 0x00;
5277 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005278 default:
5279 continue;
5280 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005281
Johan Hedberg35d70272014-02-19 14:57:47 +02005282 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005283 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005284 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005285 }
5286
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005287 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005288 NULL, 0);
5289
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005290 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005291
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005292 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005293}
5294
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005295static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005296{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005297 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005298 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005299 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005300
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005301 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005302
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005303 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005304 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005305 rp.tx_power = conn->tx_power;
5306 rp.max_tx_power = conn->max_tx_power;
5307 } else {
5308 rp.rssi = HCI_RSSI_INVALID;
5309 rp.tx_power = HCI_TX_POWER_INVALID;
5310 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005311 }
5312
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005313 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5314 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005315
5316 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005317 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005318
5319 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005320}
5321
Marcel Holtmann1904a852015-01-11 13:50:44 -08005322static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5323 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005324{
5325 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005326 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005327 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005328 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005329 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005330
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005331 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005332
5333 hci_dev_lock(hdev);
5334
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005335 /* Commands sent in request are either Read RSSI or Read Transmit Power
5336 * Level so we check which one was last sent to retrieve connection
5337 * handle. Both commands have handle as first parameter so it's safe to
5338 * cast data on the same command struct.
5339 *
5340 * First command sent is always Read RSSI and we fail only if it fails.
5341 * In other case we simply override error to indicate success as we
5342 * already remembered if TX power value is actually valid.
5343 */
5344 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5345 if (!cp) {
5346 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005347 status = MGMT_STATUS_SUCCESS;
5348 } else {
5349 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005350 }
5351
5352 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005353 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005354 goto unlock;
5355 }
5356
5357 handle = __le16_to_cpu(cp->handle);
5358 conn = hci_conn_hash_lookup_handle(hdev, handle);
5359 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005360 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005361 goto unlock;
5362 }
5363
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005364 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5365 if (!cmd)
5366 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005367
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005368 cmd->cmd_complete(cmd, status);
5369 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005370
5371unlock:
5372 hci_dev_unlock(hdev);
5373}
5374
5375static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5376 u16 len)
5377{
5378 struct mgmt_cp_get_conn_info *cp = data;
5379 struct mgmt_rp_get_conn_info rp;
5380 struct hci_conn *conn;
5381 unsigned long conn_info_age;
5382 int err = 0;
5383
5384 BT_DBG("%s", hdev->name);
5385
5386 memset(&rp, 0, sizeof(rp));
5387 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5388 rp.addr.type = cp->addr.type;
5389
5390 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005391 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5392 MGMT_STATUS_INVALID_PARAMS,
5393 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005394
5395 hci_dev_lock(hdev);
5396
5397 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005398 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5399 MGMT_STATUS_NOT_POWERED, &rp,
5400 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005401 goto unlock;
5402 }
5403
5404 if (cp->addr.type == BDADDR_BREDR)
5405 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5406 &cp->addr.bdaddr);
5407 else
5408 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5409
5410 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005411 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5412 MGMT_STATUS_NOT_CONNECTED, &rp,
5413 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005414 goto unlock;
5415 }
5416
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005417 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005418 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5419 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005420 goto unlock;
5421 }
5422
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005423 /* To avoid client trying to guess when to poll again for information we
5424 * calculate conn info age as random value between min/max set in hdev.
5425 */
5426 conn_info_age = hdev->conn_info_min_age +
5427 prandom_u32_max(hdev->conn_info_max_age -
5428 hdev->conn_info_min_age);
5429
5430 /* Query controller to refresh cached values if they are too old or were
5431 * never read.
5432 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005433 if (time_after(jiffies, conn->conn_info_timestamp +
5434 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005435 !conn->conn_info_timestamp) {
5436 struct hci_request req;
5437 struct hci_cp_read_tx_power req_txp_cp;
5438 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005439 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005440
5441 hci_req_init(&req, hdev);
5442 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5443 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5444 &req_rssi_cp);
5445
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005446 /* For LE links TX power does not change thus we don't need to
5447 * query for it once value is known.
5448 */
5449 if (!bdaddr_type_is_le(cp->addr.type) ||
5450 conn->tx_power == HCI_TX_POWER_INVALID) {
5451 req_txp_cp.handle = cpu_to_le16(conn->handle);
5452 req_txp_cp.type = 0x00;
5453 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5454 sizeof(req_txp_cp), &req_txp_cp);
5455 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005456
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005457 /* Max TX power needs to be read only once per connection */
5458 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5459 req_txp_cp.handle = cpu_to_le16(conn->handle);
5460 req_txp_cp.type = 0x01;
5461 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5462 sizeof(req_txp_cp), &req_txp_cp);
5463 }
5464
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005465 err = hci_req_run(&req, conn_info_refresh_complete);
5466 if (err < 0)
5467 goto unlock;
5468
5469 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5470 data, len);
5471 if (!cmd) {
5472 err = -ENOMEM;
5473 goto unlock;
5474 }
5475
5476 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005477 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005478 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005479
5480 conn->conn_info_timestamp = jiffies;
5481 } else {
5482 /* Cache is valid, just reply with values cached in hci_conn */
5483 rp.rssi = conn->rssi;
5484 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005485 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005486
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005487 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5488 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005489 }
5490
5491unlock:
5492 hci_dev_unlock(hdev);
5493 return err;
5494}
5495
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005496static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005497{
5498 struct hci_conn *conn = cmd->user_data;
5499 struct mgmt_rp_get_clock_info rp;
5500 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005501 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005502
5503 memset(&rp, 0, sizeof(rp));
5504 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5505
5506 if (status)
5507 goto complete;
5508
5509 hdev = hci_dev_get(cmd->index);
5510 if (hdev) {
5511 rp.local_clock = cpu_to_le32(hdev->clock);
5512 hci_dev_put(hdev);
5513 }
5514
5515 if (conn) {
5516 rp.piconet_clock = cpu_to_le32(conn->clock);
5517 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5518 }
5519
5520complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005521 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5522 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005523
5524 if (conn) {
5525 hci_conn_drop(conn);
5526 hci_conn_put(conn);
5527 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005528
5529 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005530}
5531
Marcel Holtmann1904a852015-01-11 13:50:44 -08005532static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005533{
Johan Hedberg95868422014-06-28 17:54:07 +03005534 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005535 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005536 struct hci_conn *conn;
5537
5538 BT_DBG("%s status %u", hdev->name, status);
5539
5540 hci_dev_lock(hdev);
5541
5542 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5543 if (!hci_cp)
5544 goto unlock;
5545
5546 if (hci_cp->which) {
5547 u16 handle = __le16_to_cpu(hci_cp->handle);
5548 conn = hci_conn_hash_lookup_handle(hdev, handle);
5549 } else {
5550 conn = NULL;
5551 }
5552
5553 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5554 if (!cmd)
5555 goto unlock;
5556
Johan Hedberg69487372014-12-05 13:36:07 +02005557 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005558 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005559
5560unlock:
5561 hci_dev_unlock(hdev);
5562}
5563
5564static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5565 u16 len)
5566{
5567 struct mgmt_cp_get_clock_info *cp = data;
5568 struct mgmt_rp_get_clock_info rp;
5569 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005570 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005571 struct hci_request req;
5572 struct hci_conn *conn;
5573 int err;
5574
5575 BT_DBG("%s", hdev->name);
5576
5577 memset(&rp, 0, sizeof(rp));
5578 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5579 rp.addr.type = cp->addr.type;
5580
5581 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005582 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5583 MGMT_STATUS_INVALID_PARAMS,
5584 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005585
5586 hci_dev_lock(hdev);
5587
5588 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005589 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5590 MGMT_STATUS_NOT_POWERED, &rp,
5591 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005592 goto unlock;
5593 }
5594
5595 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5596 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5597 &cp->addr.bdaddr);
5598 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005599 err = mgmt_cmd_complete(sk, hdev->id,
5600 MGMT_OP_GET_CLOCK_INFO,
5601 MGMT_STATUS_NOT_CONNECTED,
5602 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005603 goto unlock;
5604 }
5605 } else {
5606 conn = NULL;
5607 }
5608
5609 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5610 if (!cmd) {
5611 err = -ENOMEM;
5612 goto unlock;
5613 }
5614
Johan Hedberg69487372014-12-05 13:36:07 +02005615 cmd->cmd_complete = clock_info_cmd_complete;
5616
Johan Hedberg95868422014-06-28 17:54:07 +03005617 hci_req_init(&req, hdev);
5618
5619 memset(&hci_cp, 0, sizeof(hci_cp));
5620 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5621
5622 if (conn) {
5623 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005624 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005625
5626 hci_cp.handle = cpu_to_le16(conn->handle);
5627 hci_cp.which = 0x01; /* Piconet clock */
5628 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5629 }
5630
5631 err = hci_req_run(&req, get_clock_info_complete);
5632 if (err < 0)
5633 mgmt_pending_remove(cmd);
5634
5635unlock:
5636 hci_dev_unlock(hdev);
5637 return err;
5638}
5639
Johan Hedberg5a154e62014-12-19 22:26:02 +02005640static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5641{
5642 struct hci_conn *conn;
5643
5644 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5645 if (!conn)
5646 return false;
5647
5648 if (conn->dst_type != type)
5649 return false;
5650
5651 if (conn->state != BT_CONNECTED)
5652 return false;
5653
5654 return true;
5655}
5656
5657/* This function requires the caller holds hdev->lock */
5658static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5659 u8 addr_type, u8 auto_connect)
5660{
5661 struct hci_dev *hdev = req->hdev;
5662 struct hci_conn_params *params;
5663
5664 params = hci_conn_params_add(hdev, addr, addr_type);
5665 if (!params)
5666 return -EIO;
5667
5668 if (params->auto_connect == auto_connect)
5669 return 0;
5670
5671 list_del_init(&params->action);
5672
5673 switch (auto_connect) {
5674 case HCI_AUTO_CONN_DISABLED:
5675 case HCI_AUTO_CONN_LINK_LOSS:
5676 __hci_update_background_scan(req);
5677 break;
5678 case HCI_AUTO_CONN_REPORT:
5679 list_add(&params->action, &hdev->pend_le_reports);
5680 __hci_update_background_scan(req);
5681 break;
5682 case HCI_AUTO_CONN_DIRECT:
5683 case HCI_AUTO_CONN_ALWAYS:
5684 if (!is_connected(hdev, addr, addr_type)) {
5685 list_add(&params->action, &hdev->pend_le_conns);
5686 __hci_update_background_scan(req);
5687 }
5688 break;
5689 }
5690
5691 params->auto_connect = auto_connect;
5692
5693 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5694 auto_connect);
5695
5696 return 0;
5697}
5698
Marcel Holtmann8afef092014-06-29 22:28:34 +02005699static void device_added(struct sock *sk, struct hci_dev *hdev,
5700 bdaddr_t *bdaddr, u8 type, u8 action)
5701{
5702 struct mgmt_ev_device_added ev;
5703
5704 bacpy(&ev.addr.bdaddr, bdaddr);
5705 ev.addr.type = type;
5706 ev.action = action;
5707
5708 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5709}
5710
Marcel Holtmann1904a852015-01-11 13:50:44 -08005711static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005712{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005713 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005714
5715 BT_DBG("status 0x%02x", status);
5716
5717 hci_dev_lock(hdev);
5718
5719 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5720 if (!cmd)
5721 goto unlock;
5722
5723 cmd->cmd_complete(cmd, mgmt_status(status));
5724 mgmt_pending_remove(cmd);
5725
5726unlock:
5727 hci_dev_unlock(hdev);
5728}
5729
Marcel Holtmann2faade52014-06-29 19:44:03 +02005730static int add_device(struct sock *sk, struct hci_dev *hdev,
5731 void *data, u16 len)
5732{
5733 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005734 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005735 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005736 u8 auto_conn, addr_type;
5737 int err;
5738
5739 BT_DBG("%s", hdev->name);
5740
Johan Hedberg66593582014-07-09 12:59:14 +03005741 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005742 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005743 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5744 MGMT_STATUS_INVALID_PARAMS,
5745 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005746
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005747 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005748 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5749 MGMT_STATUS_INVALID_PARAMS,
5750 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005751
Johan Hedberg5a154e62014-12-19 22:26:02 +02005752 hci_req_init(&req, hdev);
5753
Marcel Holtmann2faade52014-06-29 19:44:03 +02005754 hci_dev_lock(hdev);
5755
Johan Hedberg5a154e62014-12-19 22:26:02 +02005756 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5757 if (!cmd) {
5758 err = -ENOMEM;
5759 goto unlock;
5760 }
5761
5762 cmd->cmd_complete = addr_cmd_complete;
5763
Johan Hedberg66593582014-07-09 12:59:14 +03005764 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005765 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005766 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005767 err = cmd->cmd_complete(cmd,
5768 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005769 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005770 goto unlock;
5771 }
5772
5773 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5774 cp->addr.type);
5775 if (err)
5776 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005777
Johan Hedberg5a154e62014-12-19 22:26:02 +02005778 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005779
Johan Hedberg66593582014-07-09 12:59:14 +03005780 goto added;
5781 }
5782
Marcel Holtmann2faade52014-06-29 19:44:03 +02005783 if (cp->addr.type == BDADDR_LE_PUBLIC)
5784 addr_type = ADDR_LE_DEV_PUBLIC;
5785 else
5786 addr_type = ADDR_LE_DEV_RANDOM;
5787
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005788 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005789 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005790 else if (cp->action == 0x01)
5791 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005792 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005793 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005794
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005795 /* If the connection parameters don't exist for this device,
5796 * they will be created and configured with defaults.
5797 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005798 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005799 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005800 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005801 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005802 goto unlock;
5803 }
5804
Johan Hedberg66593582014-07-09 12:59:14 +03005805added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005806 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5807
Johan Hedberg5a154e62014-12-19 22:26:02 +02005808 err = hci_req_run(&req, add_device_complete);
5809 if (err < 0) {
5810 /* ENODATA means no HCI commands were needed (e.g. if
5811 * the adapter is powered off).
5812 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005813 if (err == -ENODATA)
5814 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005815 mgmt_pending_remove(cmd);
5816 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005817
5818unlock:
5819 hci_dev_unlock(hdev);
5820 return err;
5821}
5822
Marcel Holtmann8afef092014-06-29 22:28:34 +02005823static void device_removed(struct sock *sk, struct hci_dev *hdev,
5824 bdaddr_t *bdaddr, u8 type)
5825{
5826 struct mgmt_ev_device_removed ev;
5827
5828 bacpy(&ev.addr.bdaddr, bdaddr);
5829 ev.addr.type = type;
5830
5831 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5832}
5833
Marcel Holtmann1904a852015-01-11 13:50:44 -08005834static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005835{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005836 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005837
5838 BT_DBG("status 0x%02x", status);
5839
5840 hci_dev_lock(hdev);
5841
5842 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5843 if (!cmd)
5844 goto unlock;
5845
5846 cmd->cmd_complete(cmd, mgmt_status(status));
5847 mgmt_pending_remove(cmd);
5848
5849unlock:
5850 hci_dev_unlock(hdev);
5851}
5852
Marcel Holtmann2faade52014-06-29 19:44:03 +02005853static int remove_device(struct sock *sk, struct hci_dev *hdev,
5854 void *data, u16 len)
5855{
5856 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005857 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005858 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005859 int err;
5860
5861 BT_DBG("%s", hdev->name);
5862
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005863 hci_req_init(&req, hdev);
5864
Marcel Holtmann2faade52014-06-29 19:44:03 +02005865 hci_dev_lock(hdev);
5866
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005867 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5868 if (!cmd) {
5869 err = -ENOMEM;
5870 goto unlock;
5871 }
5872
5873 cmd->cmd_complete = addr_cmd_complete;
5874
Marcel Holtmann2faade52014-06-29 19:44:03 +02005875 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005876 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005877 u8 addr_type;
5878
Johan Hedberg66593582014-07-09 12:59:14 +03005879 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005880 err = cmd->cmd_complete(cmd,
5881 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005882 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005883 goto unlock;
5884 }
5885
Johan Hedberg66593582014-07-09 12:59:14 +03005886 if (cp->addr.type == BDADDR_BREDR) {
5887 err = hci_bdaddr_list_del(&hdev->whitelist,
5888 &cp->addr.bdaddr,
5889 cp->addr.type);
5890 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005891 err = cmd->cmd_complete(cmd,
5892 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005893 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005894 goto unlock;
5895 }
5896
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005897 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005898
Johan Hedberg66593582014-07-09 12:59:14 +03005899 device_removed(sk, hdev, &cp->addr.bdaddr,
5900 cp->addr.type);
5901 goto complete;
5902 }
5903
Marcel Holtmann2faade52014-06-29 19:44:03 +02005904 if (cp->addr.type == BDADDR_LE_PUBLIC)
5905 addr_type = ADDR_LE_DEV_PUBLIC;
5906 else
5907 addr_type = ADDR_LE_DEV_RANDOM;
5908
Johan Hedbergc71593d2014-07-02 17:37:28 +03005909 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5910 addr_type);
5911 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005912 err = cmd->cmd_complete(cmd,
5913 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005914 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005915 goto unlock;
5916 }
5917
5918 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005919 err = cmd->cmd_complete(cmd,
5920 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005921 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005922 goto unlock;
5923 }
5924
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005925 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005926 list_del(&params->list);
5927 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005928 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005929
5930 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005931 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005932 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005933 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005934
Marcel Holtmann2faade52014-06-29 19:44:03 +02005935 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005936 err = cmd->cmd_complete(cmd,
5937 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005938 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005939 goto unlock;
5940 }
5941
Johan Hedberg66593582014-07-09 12:59:14 +03005942 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5943 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5944 list_del(&b->list);
5945 kfree(b);
5946 }
5947
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005948 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005949
Johan Hedberg19de0822014-07-06 13:06:51 +03005950 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5951 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5952 continue;
5953 device_removed(sk, hdev, &p->addr, p->addr_type);
5954 list_del(&p->action);
5955 list_del(&p->list);
5956 kfree(p);
5957 }
5958
5959 BT_DBG("All LE connection parameters were removed");
5960
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005961 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005962 }
5963
Johan Hedberg66593582014-07-09 12:59:14 +03005964complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005965 err = hci_req_run(&req, remove_device_complete);
5966 if (err < 0) {
5967 /* ENODATA means no HCI commands were needed (e.g. if
5968 * the adapter is powered off).
5969 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005970 if (err == -ENODATA)
5971 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005972 mgmt_pending_remove(cmd);
5973 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005974
5975unlock:
5976 hci_dev_unlock(hdev);
5977 return err;
5978}
5979
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005980static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5981 u16 len)
5982{
5983 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005984 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5985 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005986 u16 param_count, expected_len;
5987 int i;
5988
5989 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005990 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5991 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005992
5993 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005994 if (param_count > max_param_count) {
5995 BT_ERR("load_conn_param: too big param_count value %u",
5996 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005997 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5998 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005999 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006000
6001 expected_len = sizeof(*cp) + param_count *
6002 sizeof(struct mgmt_conn_param);
6003 if (expected_len != len) {
6004 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6005 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006006 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6007 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006008 }
6009
6010 BT_DBG("%s param_count %u", hdev->name, param_count);
6011
6012 hci_dev_lock(hdev);
6013
6014 hci_conn_params_clear_disabled(hdev);
6015
6016 for (i = 0; i < param_count; i++) {
6017 struct mgmt_conn_param *param = &cp->params[i];
6018 struct hci_conn_params *hci_param;
6019 u16 min, max, latency, timeout;
6020 u8 addr_type;
6021
6022 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6023 param->addr.type);
6024
6025 if (param->addr.type == BDADDR_LE_PUBLIC) {
6026 addr_type = ADDR_LE_DEV_PUBLIC;
6027 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6028 addr_type = ADDR_LE_DEV_RANDOM;
6029 } else {
6030 BT_ERR("Ignoring invalid connection parameters");
6031 continue;
6032 }
6033
6034 min = le16_to_cpu(param->min_interval);
6035 max = le16_to_cpu(param->max_interval);
6036 latency = le16_to_cpu(param->latency);
6037 timeout = le16_to_cpu(param->timeout);
6038
6039 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6040 min, max, latency, timeout);
6041
6042 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6043 BT_ERR("Ignoring invalid connection parameters");
6044 continue;
6045 }
6046
6047 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6048 addr_type);
6049 if (!hci_param) {
6050 BT_ERR("Failed to add connection parameters");
6051 continue;
6052 }
6053
6054 hci_param->conn_min_interval = min;
6055 hci_param->conn_max_interval = max;
6056 hci_param->conn_latency = latency;
6057 hci_param->supervision_timeout = timeout;
6058 }
6059
6060 hci_dev_unlock(hdev);
6061
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006062 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6063 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006064}
6065
Marcel Holtmanndbece372014-07-04 18:11:55 +02006066static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6067 void *data, u16 len)
6068{
6069 struct mgmt_cp_set_external_config *cp = data;
6070 bool changed;
6071 int err;
6072
6073 BT_DBG("%s", hdev->name);
6074
6075 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006076 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6077 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006078
6079 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006080 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6081 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006082
6083 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006084 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6085 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006086
6087 hci_dev_lock(hdev);
6088
6089 if (cp->config)
6090 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6091 &hdev->dev_flags);
6092 else
6093 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6094 &hdev->dev_flags);
6095
6096 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6097 if (err < 0)
6098 goto unlock;
6099
6100 if (!changed)
6101 goto unlock;
6102
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006103 err = new_options(hdev, sk);
6104
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006105 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006106 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006107
6108 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6109 set_bit(HCI_CONFIG, &hdev->dev_flags);
6110 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6111
6112 queue_work(hdev->req_workqueue, &hdev->power_on);
6113 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006114 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006115 mgmt_index_added(hdev);
6116 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006117 }
6118
6119unlock:
6120 hci_dev_unlock(hdev);
6121 return err;
6122}
6123
Marcel Holtmann9713c172014-07-06 12:11:15 +02006124static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6125 void *data, u16 len)
6126{
6127 struct mgmt_cp_set_public_address *cp = data;
6128 bool changed;
6129 int err;
6130
6131 BT_DBG("%s", hdev->name);
6132
6133 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006134 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6135 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006136
6137 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006138 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6139 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006140
6141 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006142 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6143 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006144
6145 hci_dev_lock(hdev);
6146
6147 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6148 bacpy(&hdev->public_addr, &cp->bdaddr);
6149
6150 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6151 if (err < 0)
6152 goto unlock;
6153
6154 if (!changed)
6155 goto unlock;
6156
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006157 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006158 err = new_options(hdev, sk);
6159
6160 if (is_configured(hdev)) {
6161 mgmt_index_removed(hdev);
6162
6163 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6164
6165 set_bit(HCI_CONFIG, &hdev->dev_flags);
6166 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6167
6168 queue_work(hdev->req_workqueue, &hdev->power_on);
6169 }
6170
6171unlock:
6172 hci_dev_unlock(hdev);
6173 return err;
6174}
6175
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006176static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006177 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006178 { read_version, MGMT_READ_VERSION_SIZE,
6179 HCI_MGMT_NO_HDEV },
6180 { read_commands, MGMT_READ_COMMANDS_SIZE,
6181 HCI_MGMT_NO_HDEV },
6182 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6183 HCI_MGMT_NO_HDEV },
6184 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6185 { set_powered, MGMT_SETTING_SIZE, 0 },
6186 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6187 { set_connectable, MGMT_SETTING_SIZE, 0 },
6188 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6189 { set_bondable, MGMT_SETTING_SIZE, 0 },
6190 { set_link_security, MGMT_SETTING_SIZE, 0 },
6191 { set_ssp, MGMT_SETTING_SIZE, 0 },
6192 { set_hs, MGMT_SETTING_SIZE, 0 },
6193 { set_le, MGMT_SETTING_SIZE, 0 },
6194 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6195 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6196 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6197 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6198 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6199 HCI_MGMT_VAR_LEN },
6200 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6201 HCI_MGMT_VAR_LEN },
6202 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6203 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6204 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6205 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6206 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6207 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6208 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6209 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6210 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6211 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6212 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6213 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6214 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6215 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6216 HCI_MGMT_VAR_LEN },
6217 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6218 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6219 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6220 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6221 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6222 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6223 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6224 { set_advertising, MGMT_SETTING_SIZE, 0 },
6225 { set_bredr, MGMT_SETTING_SIZE, 0 },
6226 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6227 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6228 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6229 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6230 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6231 { load_irks, MGMT_LOAD_IRKS_SIZE,
6232 HCI_MGMT_VAR_LEN },
6233 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6234 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6235 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6236 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6237 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6238 HCI_MGMT_VAR_LEN },
6239 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6240 HCI_MGMT_NO_HDEV },
6241 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6242 HCI_MGMT_UNCONFIGURED },
6243 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6244 HCI_MGMT_UNCONFIGURED },
6245 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6246 HCI_MGMT_UNCONFIGURED },
6247 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6248 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006249};
6250
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006251int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6252 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006253{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006254 void *buf;
6255 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006256 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006257 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006258 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006259 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006260 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006261 int err;
6262
6263 BT_DBG("got %zu bytes", msglen);
6264
6265 if (msglen < sizeof(*hdr))
6266 return -EINVAL;
6267
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006268 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006269 if (!buf)
6270 return -ENOMEM;
6271
Al Viro6ce8e9c2014-04-06 21:25:44 -04006272 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006273 err = -EFAULT;
6274 goto done;
6275 }
6276
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006277 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006278 opcode = __le16_to_cpu(hdr->opcode);
6279 index = __le16_to_cpu(hdr->index);
6280 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006281
6282 if (len != msglen - sizeof(*hdr)) {
6283 err = -EINVAL;
6284 goto done;
6285 }
6286
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006287 if (opcode >= chan->handler_count ||
6288 chan->handlers[opcode].func == NULL) {
6289 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006290 err = mgmt_cmd_status(sk, index, opcode,
6291 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006292 goto done;
6293 }
6294
6295 handler = &chan->handlers[opcode];
6296
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006297 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006298 hdev = hci_dev_get(index);
6299 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006300 err = mgmt_cmd_status(sk, index, opcode,
6301 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006302 goto done;
6303 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006304
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006305 if (hci_dev_test_flag(hdev, HCI_SETUP) ||
6306 hci_dev_test_flag(hdev, HCI_CONFIG) ||
6307 hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006308 err = mgmt_cmd_status(sk, index, opcode,
6309 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006310 goto done;
6311 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006312
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006313 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006314 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006315 err = mgmt_cmd_status(sk, index, opcode,
6316 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006317 goto done;
6318 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006319 }
6320
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006321 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6322 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006323 err = mgmt_cmd_status(sk, index, opcode,
6324 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006325 goto done;
6326 }
6327
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006328 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6329 if ((var_len && len < handler->data_len) ||
6330 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006331 err = mgmt_cmd_status(sk, index, opcode,
6332 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006333 goto done;
6334 }
6335
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006336 if (hdev)
6337 mgmt_init_hdev(sk, hdev);
6338
6339 cp = buf + sizeof(*hdr);
6340
Johan Hedbergbe22b542012-03-01 22:24:41 +02006341 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006342 if (err < 0)
6343 goto done;
6344
Johan Hedberg03811012010-12-08 00:21:06 +02006345 err = msglen;
6346
6347done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006348 if (hdev)
6349 hci_dev_put(hdev);
6350
Johan Hedberg03811012010-12-08 00:21:06 +02006351 kfree(buf);
6352 return err;
6353}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006354
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006355void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006356{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006357 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006358 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006359
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006360 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6361 return;
6362
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006363 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006364 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6365 else
6366 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006367}
6368
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006369void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006370{
Johan Hedberg5f159032012-03-02 03:13:19 +02006371 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006372
Marcel Holtmann1514b892013-10-06 08:25:01 -07006373 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006374 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006375
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006376 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6377 return;
6378
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006379 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006380
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006381 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmannedd38962014-07-02 21:30:55 +02006382 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6383 else
6384 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006385}
6386
Andre Guedes6046dc32014-02-26 20:21:51 -03006387/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006388static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006389{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006390 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006391 struct hci_conn_params *p;
6392
6393 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006394 /* Needed for AUTO_OFF case where might not "really"
6395 * have been powered off.
6396 */
6397 list_del_init(&p->action);
6398
6399 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006400 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006401 case HCI_AUTO_CONN_ALWAYS:
6402 list_add(&p->action, &hdev->pend_le_conns);
6403 break;
6404 case HCI_AUTO_CONN_REPORT:
6405 list_add(&p->action, &hdev->pend_le_reports);
6406 break;
6407 default:
6408 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006409 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006410 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006411
Johan Hedberg2cf22212014-12-19 22:26:00 +02006412 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006413}
6414
Marcel Holtmann1904a852015-01-11 13:50:44 -08006415static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006416{
6417 struct cmd_lookup match = { NULL, hdev };
6418
6419 BT_DBG("status 0x%02x", status);
6420
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006421 if (!status) {
6422 /* Register the available SMP channels (BR/EDR and LE) only
6423 * when successfully powering on the controller. This late
6424 * registration is required so that LE SMP can clearly
6425 * decide if the public address or static address is used.
6426 */
6427 smp_register(hdev);
6428 }
6429
Johan Hedberg229ab392013-03-15 17:06:53 -05006430 hci_dev_lock(hdev);
6431
6432 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6433
6434 new_settings(hdev, match.sk);
6435
6436 hci_dev_unlock(hdev);
6437
6438 if (match.sk)
6439 sock_put(match.sk);
6440}
6441
Johan Hedberg70da6242013-03-15 17:06:51 -05006442static int powered_update_hci(struct hci_dev *hdev)
6443{
Johan Hedberg890ea892013-03-15 17:06:52 -05006444 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006445 u8 link_sec;
6446
Johan Hedberg890ea892013-03-15 17:06:52 -05006447 hci_req_init(&req, hdev);
6448
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006449 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05006450 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006451 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006452
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006453 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006454
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006455 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6456 u8 support = 0x01;
6457
6458 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6459 sizeof(support), &support);
6460 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006461 }
6462
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006463 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03006464 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006465 struct hci_cp_write_le_host_supported cp;
6466
Marcel Holtmann32226e42014-07-24 20:04:16 +02006467 cp.le = 0x01;
6468 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006469
6470 /* Check first if we already have the right
6471 * host state (host features set)
6472 */
6473 if (cp.le != lmp_host_le_capable(hdev) ||
6474 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006475 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6476 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006477 }
6478
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006479 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006480 /* Make sure the controller has a good default for
6481 * advertising data. This also applies to the case
6482 * where BR/EDR was toggled during the AUTO_OFF phase.
6483 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006484 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006485 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006486 update_scan_rsp_data(&req);
6487 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006488
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006489 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006490 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006491
6492 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006493 }
6494
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006495 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05006496 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006497 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6498 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006499
6500 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006501 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006502 write_fast_connectable(&req, true);
6503 else
6504 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006505 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006506 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006507 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006508 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006509 }
6510
Johan Hedberg229ab392013-03-15 17:06:53 -05006511 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006512}
6513
Johan Hedberg744cf192011-11-08 20:40:14 +02006514int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006515{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006516 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006517 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006518 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006519
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006520 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006521 return 0;
6522
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006523 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006524 if (powered_update_hci(hdev) == 0)
6525 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006526
Johan Hedberg229ab392013-03-15 17:06:53 -05006527 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6528 &match);
6529 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006530 }
6531
Johan Hedberg229ab392013-03-15 17:06:53 -05006532 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006533
6534 /* If the power off is because of hdev unregistration let
6535 * use the appropriate INVALID_INDEX status. Otherwise use
6536 * NOT_POWERED. We cover both scenarios here since later in
6537 * mgmt_index_removed() any hci_conn callbacks will have already
6538 * been triggered, potentially causing misleading DISCONNECTED
6539 * status responses.
6540 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006541 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02006542 status = MGMT_STATUS_INVALID_INDEX;
6543 else
6544 status = MGMT_STATUS_NOT_POWERED;
6545
6546 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006547
6548 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6549 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6550 zero_cod, sizeof(zero_cod), NULL);
6551
6552new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006553 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006554
6555 if (match.sk)
6556 sock_put(match.sk);
6557
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006558 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006559}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006560
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006561void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006562{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006563 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006564 u8 status;
6565
6566 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6567 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006568 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006569
6570 if (err == -ERFKILL)
6571 status = MGMT_STATUS_RFKILLED;
6572 else
6573 status = MGMT_STATUS_FAILED;
6574
Johan Hedberga69e8372015-03-06 21:08:53 +02006575 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006576
6577 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006578}
6579
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006580void mgmt_discoverable_timeout(struct hci_dev *hdev)
6581{
6582 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006583
6584 hci_dev_lock(hdev);
6585
6586 /* When discoverable timeout triggers, then just make sure
6587 * the limited discoverable flag is cleared. Even in the case
6588 * of a timeout triggered from general discoverable, it is
6589 * safe to unconditionally clear the flag.
6590 */
6591 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006592 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006593
6594 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006595 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03006596 u8 scan = SCAN_PAGE;
6597 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6598 sizeof(scan), &scan);
6599 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006600 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006601 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006602 hci_req_run(&req, NULL);
6603
6604 hdev->discov_timeout = 0;
6605
Johan Hedberg9a43e252013-10-20 19:00:07 +03006606 new_settings(hdev, NULL);
6607
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006608 hci_dev_unlock(hdev);
6609}
6610
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006611void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6612 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006613{
Johan Hedberg86742e12011-11-07 23:13:38 +02006614 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006615
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006616 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006617
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006618 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006619 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006620 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006621 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006622 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006623 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006624
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006625 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006626}
Johan Hedbergf7520542011-01-20 12:34:39 +02006627
Johan Hedbergd7b25452014-05-23 13:19:53 +03006628static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6629{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006630 switch (ltk->type) {
6631 case SMP_LTK:
6632 case SMP_LTK_SLAVE:
6633 if (ltk->authenticated)
6634 return MGMT_LTK_AUTHENTICATED;
6635 return MGMT_LTK_UNAUTHENTICATED;
6636 case SMP_LTK_P256:
6637 if (ltk->authenticated)
6638 return MGMT_LTK_P256_AUTH;
6639 return MGMT_LTK_P256_UNAUTH;
6640 case SMP_LTK_P256_DEBUG:
6641 return MGMT_LTK_P256_DEBUG;
6642 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006643
6644 return MGMT_LTK_UNAUTHENTICATED;
6645}
6646
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006647void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006648{
6649 struct mgmt_ev_new_long_term_key ev;
6650
6651 memset(&ev, 0, sizeof(ev));
6652
Marcel Holtmann5192d302014-02-19 17:11:58 -08006653 /* Devices using resolvable or non-resolvable random addresses
6654 * without providing an indentity resolving key don't require
6655 * to store long term keys. Their addresses will change the
6656 * next time around.
6657 *
6658 * Only when a remote device provides an identity address
6659 * make sure the long term key is stored. If the remote
6660 * identity is known, the long term keys are internally
6661 * mapped to the identity address. So allow static random
6662 * and public addresses here.
6663 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006664 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6665 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6666 ev.store_hint = 0x00;
6667 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006668 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006669
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006670 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006671 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006672 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006673 ev.key.enc_size = key->enc_size;
6674 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006675 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006676
Johan Hedberg2ceba532014-06-16 19:25:16 +03006677 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006678 ev.key.master = 1;
6679
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006680 memcpy(ev.key.val, key->val, sizeof(key->val));
6681
Marcel Holtmann083368f2013-10-15 14:26:29 -07006682 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006683}
6684
Johan Hedberg95fbac82014-02-19 15:18:31 +02006685void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6686{
6687 struct mgmt_ev_new_irk ev;
6688
6689 memset(&ev, 0, sizeof(ev));
6690
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006691 /* For identity resolving keys from devices that are already
6692 * using a public address or static random address, do not
6693 * ask for storing this key. The identity resolving key really
6694 * is only mandatory for devices using resovlable random
6695 * addresses.
6696 *
6697 * Storing all identity resolving keys has the downside that
6698 * they will be also loaded on next boot of they system. More
6699 * identity resolving keys, means more time during scanning is
6700 * needed to actually resolve these addresses.
6701 */
6702 if (bacmp(&irk->rpa, BDADDR_ANY))
6703 ev.store_hint = 0x01;
6704 else
6705 ev.store_hint = 0x00;
6706
Johan Hedberg95fbac82014-02-19 15:18:31 +02006707 bacpy(&ev.rpa, &irk->rpa);
6708 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6709 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6710 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6711
6712 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6713}
6714
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006715void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6716 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006717{
6718 struct mgmt_ev_new_csrk ev;
6719
6720 memset(&ev, 0, sizeof(ev));
6721
6722 /* Devices using resolvable or non-resolvable random addresses
6723 * without providing an indentity resolving key don't require
6724 * to store signature resolving keys. Their addresses will change
6725 * the next time around.
6726 *
6727 * Only when a remote device provides an identity address
6728 * make sure the signature resolving key is stored. So allow
6729 * static random and public addresses here.
6730 */
6731 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6732 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6733 ev.store_hint = 0x00;
6734 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006735 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006736
6737 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6738 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006739 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006740 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6741
6742 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6743}
6744
Andre Guedesffb5a8272014-07-01 18:10:11 -03006745void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006746 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6747 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006748{
6749 struct mgmt_ev_new_conn_param ev;
6750
Johan Hedbergc103aea2014-07-02 17:37:34 +03006751 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6752 return;
6753
Andre Guedesffb5a8272014-07-01 18:10:11 -03006754 memset(&ev, 0, sizeof(ev));
6755 bacpy(&ev.addr.bdaddr, bdaddr);
6756 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006757 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006758 ev.min_interval = cpu_to_le16(min_interval);
6759 ev.max_interval = cpu_to_le16(max_interval);
6760 ev.latency = cpu_to_le16(latency);
6761 ev.timeout = cpu_to_le16(timeout);
6762
6763 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6764}
6765
Marcel Holtmann94933992013-10-15 10:26:39 -07006766static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6767 u8 data_len)
6768{
6769 eir[eir_len++] = sizeof(type) + data_len;
6770 eir[eir_len++] = type;
6771 memcpy(&eir[eir_len], data, data_len);
6772 eir_len += data_len;
6773
6774 return eir_len;
6775}
6776
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006777void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6778 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006779{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006780 char buf[512];
6781 struct mgmt_ev_device_connected *ev = (void *) buf;
6782 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006783
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006784 bacpy(&ev->addr.bdaddr, &conn->dst);
6785 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006786
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006787 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006788
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006789 /* We must ensure that the EIR Data fields are ordered and
6790 * unique. Keep it simple for now and avoid the problem by not
6791 * adding any BR/EDR data to the LE adv.
6792 */
6793 if (conn->le_adv_data_len > 0) {
6794 memcpy(&ev->eir[eir_len],
6795 conn->le_adv_data, conn->le_adv_data_len);
6796 eir_len = conn->le_adv_data_len;
6797 } else {
6798 if (name_len > 0)
6799 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6800 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006801
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006802 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006803 eir_len = eir_append_data(ev->eir, eir_len,
6804 EIR_CLASS_OF_DEV,
6805 conn->dev_class, 3);
6806 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006807
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006808 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006809
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006810 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6811 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006812}
6813
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006814static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006815{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006816 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006817
Johan Hedbergf5818c22014-12-05 13:36:02 +02006818 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006819
6820 *sk = cmd->sk;
6821 sock_hold(*sk);
6822
Johan Hedberga664b5b2011-02-19 12:06:02 -03006823 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006824}
6825
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006826static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006827{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006828 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006829 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006830
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006831 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6832
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006833 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006834 mgmt_pending_remove(cmd);
6835}
6836
Johan Hedberg84c61d92014-08-01 11:13:30 +03006837bool mgmt_powering_down(struct hci_dev *hdev)
6838{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006839 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006840 struct mgmt_mode *cp;
6841
6842 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6843 if (!cmd)
6844 return false;
6845
6846 cp = cmd->param;
6847 if (!cp->val)
6848 return true;
6849
6850 return false;
6851}
6852
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006853void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006854 u8 link_type, u8 addr_type, u8 reason,
6855 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006856{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006857 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006858 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006859
Johan Hedberg84c61d92014-08-01 11:13:30 +03006860 /* The connection is still in hci_conn_hash so test for 1
6861 * instead of 0 to know if this is the last one.
6862 */
6863 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6864 cancel_delayed_work(&hdev->power_off);
6865 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006866 }
6867
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006868 if (!mgmt_connected)
6869 return;
6870
Andre Guedes57eb7762013-10-30 19:01:41 -03006871 if (link_type != ACL_LINK && link_type != LE_LINK)
6872 return;
6873
Johan Hedberg744cf192011-11-08 20:40:14 +02006874 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006875
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006876 bacpy(&ev.addr.bdaddr, bdaddr);
6877 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6878 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006879
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006880 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006881
6882 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006883 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006884
Johan Hedberg124f6e32012-02-09 13:50:12 +02006885 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006886 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006887}
6888
Marcel Holtmann78929242013-10-06 23:55:47 -07006889void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6890 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006891{
Andre Guedes3655bba2013-10-30 19:01:40 -03006892 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6893 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006894 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006895
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006896 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6897 hdev);
6898
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006899 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006900 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006901 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006902
Andre Guedes3655bba2013-10-30 19:01:40 -03006903 cp = cmd->param;
6904
6905 if (bacmp(bdaddr, &cp->addr.bdaddr))
6906 return;
6907
6908 if (cp->addr.type != bdaddr_type)
6909 return;
6910
Johan Hedbergf5818c22014-12-05 13:36:02 +02006911 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006912 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006913}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006914
Marcel Holtmann445608d2013-10-06 23:55:48 -07006915void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6916 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006917{
6918 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006919
Johan Hedberg84c61d92014-08-01 11:13:30 +03006920 /* The connection is still in hci_conn_hash so test for 1
6921 * instead of 0 to know if this is the last one.
6922 */
6923 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6924 cancel_delayed_work(&hdev->power_off);
6925 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006926 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006927
Johan Hedberg4c659c32011-11-07 23:13:39 +02006928 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006929 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006930 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006931
Marcel Holtmann445608d2013-10-06 23:55:48 -07006932 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006933}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006934
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006935void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006936{
6937 struct mgmt_ev_pin_code_request ev;
6938
Johan Hedbergd8457692012-02-17 14:24:57 +02006939 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006940 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006941 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006942
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006943 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006944}
6945
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006946void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6947 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006948{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006949 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006950
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006951 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006952 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006953 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006954
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006955 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006956 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006957}
6958
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006959void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6960 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006961{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006962 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006963
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006964 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006965 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006966 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006967
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006968 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006969 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006970}
Johan Hedberga5c29682011-02-19 12:05:57 -03006971
Johan Hedberg744cf192011-11-08 20:40:14 +02006972int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006973 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006974 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006975{
6976 struct mgmt_ev_user_confirm_request ev;
6977
Johan Hedberg744cf192011-11-08 20:40:14 +02006978 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006979
Johan Hedberg272d90d2012-02-09 15:26:12 +02006980 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006981 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006982 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006983 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006984
Johan Hedberg744cf192011-11-08 20:40:14 +02006985 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006986 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006987}
6988
Johan Hedberg272d90d2012-02-09 15:26:12 +02006989int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006990 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006991{
6992 struct mgmt_ev_user_passkey_request ev;
6993
6994 BT_DBG("%s", hdev->name);
6995
Johan Hedberg272d90d2012-02-09 15:26:12 +02006996 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006997 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006998
6999 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007000 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007001}
7002
Brian Gix0df4c182011-11-16 13:53:13 -08007003static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007004 u8 link_type, u8 addr_type, u8 status,
7005 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007006{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007007 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007008
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007009 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007010 if (!cmd)
7011 return -ENOENT;
7012
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007013 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007014 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007015
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007016 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007017}
7018
Johan Hedberg744cf192011-11-08 20:40:14 +02007019int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007020 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007021{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007022 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007023 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007024}
7025
Johan Hedberg272d90d2012-02-09 15:26:12 +02007026int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007027 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007028{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007029 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007030 status,
7031 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007032}
Johan Hedberg2a611692011-02-19 12:06:00 -03007033
Brian Gix604086b2011-11-23 08:28:33 -08007034int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007035 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007036{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007037 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007038 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007039}
7040
Johan Hedberg272d90d2012-02-09 15:26:12 +02007041int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007042 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007043{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007044 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007045 status,
7046 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007047}
7048
Johan Hedberg92a25252012-09-06 18:39:26 +03007049int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7050 u8 link_type, u8 addr_type, u32 passkey,
7051 u8 entered)
7052{
7053 struct mgmt_ev_passkey_notify ev;
7054
7055 BT_DBG("%s", hdev->name);
7056
7057 bacpy(&ev.addr.bdaddr, bdaddr);
7058 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7059 ev.passkey = __cpu_to_le32(passkey);
7060 ev.entered = entered;
7061
7062 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7063}
7064
Johan Hedberge1e930f2014-09-08 17:09:49 -07007065void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007066{
7067 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007068 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007069 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007070
Johan Hedberge1e930f2014-09-08 17:09:49 -07007071 bacpy(&ev.addr.bdaddr, &conn->dst);
7072 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7073 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007074
Johan Hedberge1e930f2014-09-08 17:09:49 -07007075 cmd = find_pairing(conn);
7076
7077 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7078 cmd ? cmd->sk : NULL);
7079
Johan Hedberga511b352014-12-11 21:45:45 +02007080 if (cmd) {
7081 cmd->cmd_complete(cmd, status);
7082 mgmt_pending_remove(cmd);
7083 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007084}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007085
Marcel Holtmann464996a2013-10-15 14:26:24 -07007086void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007087{
7088 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007089 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007090
7091 if (status) {
7092 u8 mgmt_err = mgmt_status(status);
7093 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007094 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007095 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007096 }
7097
Marcel Holtmann464996a2013-10-15 14:26:24 -07007098 if (test_bit(HCI_AUTH, &hdev->flags))
7099 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7100 &hdev->dev_flags);
7101 else
7102 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7103 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007104
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007105 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007106 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007107
Johan Hedberg47990ea2012-02-22 11:58:37 +02007108 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007109 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007110
7111 if (match.sk)
7112 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007113}
7114
Johan Hedberg890ea892013-03-15 17:06:52 -05007115static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007116{
Johan Hedberg890ea892013-03-15 17:06:52 -05007117 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007118 struct hci_cp_write_eir cp;
7119
Johan Hedberg976eb202012-10-24 21:12:01 +03007120 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007121 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007122
Johan Hedbergc80da272012-02-22 15:38:48 +02007123 memset(hdev->eir, 0, sizeof(hdev->eir));
7124
Johan Hedbergcacaf522012-02-21 00:52:42 +02007125 memset(&cp, 0, sizeof(cp));
7126
Johan Hedberg890ea892013-03-15 17:06:52 -05007127 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007128}
7129
Marcel Holtmann3e248562013-10-15 14:26:25 -07007130void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007131{
7132 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007133 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007134 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007135
7136 if (status) {
7137 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007138
7139 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007140 &hdev->dev_flags)) {
7141 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007142 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007143 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007144
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007145 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7146 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007147 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007148 }
7149
7150 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007151 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007152 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007153 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7154 if (!changed)
7155 changed = test_and_clear_bit(HCI_HS_ENABLED,
7156 &hdev->dev_flags);
7157 else
7158 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007159 }
7160
7161 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7162
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007163 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007164 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007165
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007166 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007167 sock_put(match.sk);
7168
Johan Hedberg890ea892013-03-15 17:06:52 -05007169 hci_req_init(&req, hdev);
7170
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007171 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7172 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007173 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7174 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007175 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007176 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007177 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007178 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007179
7180 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007181}
7182
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007183static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007184{
7185 struct cmd_lookup *match = data;
7186
Johan Hedberg90e70452012-02-23 23:09:40 +02007187 if (match->sk == NULL) {
7188 match->sk = cmd->sk;
7189 sock_hold(match->sk);
7190 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007191}
7192
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007193void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7194 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007195{
Johan Hedberg90e70452012-02-23 23:09:40 +02007196 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007197
Johan Hedberg92da6092013-03-15 17:06:55 -05007198 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7199 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7200 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007201
7202 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007203 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7204 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007205
7206 if (match.sk)
7207 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007208}
7209
Marcel Holtmann7667da32013-10-15 14:26:27 -07007210void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007211{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007212 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007213 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007214
Johan Hedberg13928972013-03-15 17:07:00 -05007215 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007216 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007217
7218 memset(&ev, 0, sizeof(ev));
7219 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007220 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007221
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007222 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007223 if (!cmd) {
7224 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007225
Johan Hedberg13928972013-03-15 17:07:00 -05007226 /* If this is a HCI command related to powering on the
7227 * HCI dev don't send any mgmt signals.
7228 */
7229 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007230 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007231 }
7232
Marcel Holtmann7667da32013-10-15 14:26:27 -07007233 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7234 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007235}
Szymon Jancc35938b2011-03-22 13:12:21 +01007236
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007237void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007238 u8 *rand192, u8 *hash256, u8 *rand256,
7239 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007240{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007241 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007242
Johan Hedberg744cf192011-11-08 20:40:14 +02007243 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007244
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007245 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007246 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007247 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007248
7249 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007250 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7251 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007252 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007253 struct mgmt_rp_read_local_oob_data rp;
7254 size_t rp_size = sizeof(rp);
7255
7256 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7257 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7258
Johan Hedberg710f11c2014-05-26 11:21:22 +03007259 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007260 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007261 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007262 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007263 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007264 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007265
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007266 mgmt_cmd_complete(cmd->sk, hdev->id,
7267 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7268 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007269 }
7270
7271 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007272}
Johan Hedberge17acd42011-03-30 23:57:16 +03007273
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007274static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7275{
7276 int i;
7277
7278 for (i = 0; i < uuid_count; i++) {
7279 if (!memcmp(uuid, uuids[i], 16))
7280 return true;
7281 }
7282
7283 return false;
7284}
7285
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007286static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7287{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007288 u16 parsed = 0;
7289
7290 while (parsed < eir_len) {
7291 u8 field_len = eir[0];
7292 u8 uuid[16];
7293 int i;
7294
7295 if (field_len == 0)
7296 break;
7297
7298 if (eir_len - parsed < field_len + 1)
7299 break;
7300
7301 switch (eir[1]) {
7302 case EIR_UUID16_ALL:
7303 case EIR_UUID16_SOME:
7304 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007305 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007306 uuid[13] = eir[i + 3];
7307 uuid[12] = eir[i + 2];
7308 if (has_uuid(uuid, uuid_count, uuids))
7309 return true;
7310 }
7311 break;
7312 case EIR_UUID32_ALL:
7313 case EIR_UUID32_SOME:
7314 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007315 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007316 uuid[15] = eir[i + 5];
7317 uuid[14] = eir[i + 4];
7318 uuid[13] = eir[i + 3];
7319 uuid[12] = eir[i + 2];
7320 if (has_uuid(uuid, uuid_count, uuids))
7321 return true;
7322 }
7323 break;
7324 case EIR_UUID128_ALL:
7325 case EIR_UUID128_SOME:
7326 for (i = 0; i + 17 <= field_len; i += 16) {
7327 memcpy(uuid, eir + i + 2, 16);
7328 if (has_uuid(uuid, uuid_count, uuids))
7329 return true;
7330 }
7331 break;
7332 }
7333
7334 parsed += field_len + 1;
7335 eir += field_len + 1;
7336 }
7337
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007338 return false;
7339}
7340
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007341static void restart_le_scan(struct hci_dev *hdev)
7342{
7343 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007344 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007345 return;
7346
7347 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7348 hdev->discovery.scan_start +
7349 hdev->discovery.scan_duration))
7350 return;
7351
7352 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7353 DISCOV_LE_RESTART_DELAY);
7354}
7355
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007356static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7357 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7358{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007359 /* If a RSSI threshold has been specified, and
7360 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7361 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7362 * is set, let it through for further processing, as we might need to
7363 * restart the scan.
7364 *
7365 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7366 * the results are also dropped.
7367 */
7368 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7369 (rssi == HCI_RSSI_INVALID ||
7370 (rssi < hdev->discovery.rssi &&
7371 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7372 return false;
7373
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007374 if (hdev->discovery.uuid_count != 0) {
7375 /* If a list of UUIDs is provided in filter, results with no
7376 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007377 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007378 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7379 hdev->discovery.uuids) &&
7380 !eir_has_uuids(scan_rsp, scan_rsp_len,
7381 hdev->discovery.uuid_count,
7382 hdev->discovery.uuids))
7383 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007384 }
7385
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007386 /* If duplicate filtering does not report RSSI changes, then restart
7387 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007388 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007389 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7390 restart_le_scan(hdev);
7391
7392 /* Validate RSSI value against the RSSI threshold once more. */
7393 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7394 rssi < hdev->discovery.rssi)
7395 return false;
7396 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007397
7398 return true;
7399}
7400
Marcel Holtmann901801b2013-10-06 23:55:51 -07007401void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007402 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7403 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007404{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007405 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007406 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007407 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007408
Johan Hedberg75ce2082014-07-02 22:42:01 +03007409 /* Don't send events for a non-kernel initiated discovery. With
7410 * LE one exception is if we have pend_le_reports > 0 in which
7411 * case we're doing passive scanning and want these events.
7412 */
7413 if (!hci_discovery_active(hdev)) {
7414 if (link_type == ACL_LINK)
7415 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007416 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007417 return;
7418 }
Andre Guedes12602d02013-04-30 15:29:40 -03007419
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007420 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007421 /* We are using service discovery */
7422 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7423 scan_rsp_len))
7424 return;
7425 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007426
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007427 /* Make sure that the buffer is big enough. The 5 extra bytes
7428 * are for the potential CoD field.
7429 */
7430 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007431 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007432
Johan Hedberg1dc06092012-01-15 21:01:23 +02007433 memset(buf, 0, sizeof(buf));
7434
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007435 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7436 * RSSI value was reported as 0 when not available. This behavior
7437 * is kept when using device discovery. This is required for full
7438 * backwards compatibility with the API.
7439 *
7440 * However when using service discovery, the value 127 will be
7441 * returned when the RSSI is not available.
7442 */
Szymon Janc91200e92015-01-22 16:57:05 +01007443 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7444 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007445 rssi = 0;
7446
Johan Hedberg841c5642014-07-07 12:45:54 +03007447 bacpy(&ev->addr.bdaddr, bdaddr);
7448 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007449 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007450 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007451
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007452 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007453 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007454 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007455
Johan Hedberg1dc06092012-01-15 21:01:23 +02007456 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7457 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007458 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007459
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007460 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007461 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007462 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007463
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007464 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7465 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007466
Marcel Holtmann901801b2013-10-06 23:55:51 -07007467 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007468}
Johan Hedberga88a9652011-03-30 13:18:12 +03007469
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007470void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7471 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007472{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007473 struct mgmt_ev_device_found *ev;
7474 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7475 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007476
Johan Hedbergb644ba32012-01-17 21:48:47 +02007477 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007478
Johan Hedbergb644ba32012-01-17 21:48:47 +02007479 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007480
Johan Hedbergb644ba32012-01-17 21:48:47 +02007481 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007482 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007483 ev->rssi = rssi;
7484
7485 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007486 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007487
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007488 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007489
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007490 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007491}
Johan Hedberg314b2382011-04-27 10:29:57 -04007492
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007493void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007494{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007495 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007496
Andre Guedes343fb142011-11-22 17:14:19 -03007497 BT_DBG("%s discovering %u", hdev->name, discovering);
7498
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007499 memset(&ev, 0, sizeof(ev));
7500 ev.type = hdev->discovery.type;
7501 ev.discovering = discovering;
7502
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007503 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007504}
Antti Julku5e762442011-08-25 16:48:02 +03007505
Marcel Holtmann1904a852015-01-11 13:50:44 -08007506static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007507{
7508 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007509}
7510
7511void mgmt_reenable_advertising(struct hci_dev *hdev)
7512{
7513 struct hci_request req;
7514
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007515 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmann5976e602013-10-06 04:08:14 -07007516 return;
7517
7518 hci_req_init(&req, hdev);
7519 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007520 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007521}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007522
7523static struct hci_mgmt_chan chan = {
7524 .channel = HCI_CHANNEL_CONTROL,
7525 .handler_count = ARRAY_SIZE(mgmt_handlers),
7526 .handlers = mgmt_handlers,
7527};
7528
7529int mgmt_init(void)
7530{
7531 return hci_mgmt_chan_register(&chan);
7532}
7533
7534void mgmt_exit(void)
7535{
7536 hci_mgmt_chan_unregister(&chan);
7537}