blob: cc5c047288480aecf477fc79ab6723a2b257f719 [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 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001111 hci_dev_clear_flag(hdev, HCI_LE_ADV);
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
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001143 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
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
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001166 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001167
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 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001192 hci_dev_clear_flag(hdev, HCI_BONDABLE);
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 Holtmanna69d8922015-03-13 02:11:05 -07001422 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001423 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 Holtmanna358dc12015-03-13 02:11:02 -07001576 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
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 {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001591 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001592 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001593
1594 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1595
1596 if (changed)
1597 new_settings(hdev, cmd->sk);
1598
Marcel Holtmann970ba522013-10-15 06:33:57 -07001599 /* When the discoverable mode gets changed, make sure
1600 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001601 * bit correctly set. Also update page scan based on whitelist
1602 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001603 */
1604 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001605 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001606 update_class(&req);
1607 hci_req_run(&req, NULL);
1608
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001609remove_cmd:
1610 mgmt_pending_remove(cmd);
1611
1612unlock:
1613 hci_dev_unlock(hdev);
1614}
1615
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001616static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001617 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001618{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001619 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001620 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001621 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001622 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001623 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001624 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001625
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001626 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001627
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001628 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1629 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001630 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1631 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001632
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001633 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001634 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1635 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001636
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001637 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001638
1639 /* Disabling discoverable requires that no timeout is set,
1640 * and enabling limited discoverable requires a timeout.
1641 */
1642 if ((cp->val == 0x00 && timeout > 0) ||
1643 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001644 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1645 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001646
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001647 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001648
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001649 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001650 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1651 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001652 goto failed;
1653 }
1654
1655 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001656 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001657 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1658 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001659 goto failed;
1660 }
1661
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001662 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001663 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1664 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001665 goto failed;
1666 }
1667
1668 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001669 bool changed = false;
1670
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001671 /* Setting limited discoverable when powered off is
1672 * not a valid operation since it requires a timeout
1673 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1674 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001675 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001676 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001677 changed = true;
1678 }
1679
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001680 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001681 if (err < 0)
1682 goto failed;
1683
1684 if (changed)
1685 err = new_settings(hdev, sk);
1686
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001687 goto failed;
1688 }
1689
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001690 /* If the current mode is the same, then just update the timeout
1691 * value with the new value. And if only the timeout gets updated,
1692 * then no need for any HCI transactions.
1693 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001694 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1695 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1696 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001697 cancel_delayed_work(&hdev->discov_off);
1698 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001699
Marcel Holtmann36261542013-10-15 08:28:51 -07001700 if (cp->val && hdev->discov_timeout > 0) {
1701 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001702 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001703 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001704 }
1705
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001706 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001707 goto failed;
1708 }
1709
1710 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1711 if (!cmd) {
1712 err = -ENOMEM;
1713 goto failed;
1714 }
1715
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001716 /* Cancel any potential discoverable timeout that might be
1717 * still active and store new timeout value. The arming of
1718 * the timeout happens in the complete handler.
1719 */
1720 cancel_delayed_work(&hdev->discov_off);
1721 hdev->discov_timeout = timeout;
1722
Johan Hedbergb456f872013-10-19 23:38:22 +03001723 /* Limited discoverable mode */
1724 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001725 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001726 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001727 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001728
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001729 hci_req_init(&req, hdev);
1730
Johan Hedberg9a43e252013-10-20 19:00:07 +03001731 /* The procedure for LE-only controllers is much simpler - just
1732 * update the advertising data.
1733 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001734 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001735 goto update_ad;
1736
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001737 scan = SCAN_PAGE;
1738
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001739 if (cp->val) {
1740 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001741
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001742 if (cp->val == 0x02) {
1743 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001744 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001745 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1746 hci_cp.iac_lap[1] = 0x8b;
1747 hci_cp.iac_lap[2] = 0x9e;
1748 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1749 hci_cp.iac_lap[4] = 0x8b;
1750 hci_cp.iac_lap[5] = 0x9e;
1751 } else {
1752 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001753 hci_cp.num_iac = 1;
1754 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1755 hci_cp.iac_lap[1] = 0x8b;
1756 hci_cp.iac_lap[2] = 0x9e;
1757 }
1758
1759 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1760 (hci_cp.num_iac * 3) + 1, &hci_cp);
1761
1762 scan |= SCAN_INQUIRY;
1763 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001764 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001765 }
1766
1767 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001768
Johan Hedberg9a43e252013-10-20 19:00:07 +03001769update_ad:
1770 update_adv_data(&req);
1771
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001772 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001773 if (err < 0)
1774 mgmt_pending_remove(cmd);
1775
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001776failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001777 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001778 return err;
1779}
1780
Johan Hedberg406d7802013-03-15 17:07:09 -05001781static void write_fast_connectable(struct hci_request *req, bool enable)
1782{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001783 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001784 struct hci_cp_write_page_scan_activity acp;
1785 u8 type;
1786
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001787 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001788 return;
1789
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001790 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1791 return;
1792
Johan Hedberg406d7802013-03-15 17:07:09 -05001793 if (enable) {
1794 type = PAGE_SCAN_TYPE_INTERLACED;
1795
1796 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001797 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001798 } else {
1799 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1800
1801 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001802 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001803 }
1804
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001805 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001806
Johan Hedbergbd98b992013-03-15 17:07:13 -05001807 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1808 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1809 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1810 sizeof(acp), &acp);
1811
1812 if (hdev->page_scan_type != type)
1813 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001814}
1815
Marcel Holtmann1904a852015-01-11 13:50:44 -08001816static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1817 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001818{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001819 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001820 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001821 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001822
1823 BT_DBG("status 0x%02x", status);
1824
1825 hci_dev_lock(hdev);
1826
1827 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1828 if (!cmd)
1829 goto unlock;
1830
Johan Hedberg37438c12013-10-14 16:20:05 +03001831 if (status) {
1832 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001833 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001834 goto remove_cmd;
1835 }
1836
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001837 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001838 if (cp->val) {
1839 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1840 &hdev->dev_flags);
1841 discov_changed = false;
1842 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001843 conn_changed = hci_dev_test_and_clear_flag(hdev,
1844 HCI_CONNECTABLE);
1845 discov_changed = hci_dev_test_and_clear_flag(hdev,
1846 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001847 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001848
Johan Hedberg2b76f452013-03-15 17:07:04 -05001849 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1850
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001851 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001852 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001853 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001854 if (discov_changed)
1855 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001856 hci_update_background_scan(hdev);
1857 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001858
Johan Hedberg37438c12013-10-14 16:20:05 +03001859remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001860 mgmt_pending_remove(cmd);
1861
1862unlock:
1863 hci_dev_unlock(hdev);
1864}
1865
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001866static int set_connectable_update_settings(struct hci_dev *hdev,
1867 struct sock *sk, u8 val)
1868{
1869 bool changed = false;
1870 int err;
1871
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001872 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001873 changed = true;
1874
1875 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001876 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001877 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001878 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
1879 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001880 }
1881
1882 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1883 if (err < 0)
1884 return err;
1885
Johan Hedberg562064e2014-07-08 16:35:34 +03001886 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001887 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001888 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001889 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001890 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001891
1892 return 0;
1893}
1894
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001895static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001896 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001897{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001898 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001899 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001900 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001901 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001902 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001903
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001904 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001905
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001906 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1907 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001908 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1909 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001910
Johan Hedberga7e80f22013-01-09 16:05:19 +02001911 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001912 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1913 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001914
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001915 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001916
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001917 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001918 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001919 goto failed;
1920 }
1921
1922 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001923 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001924 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1925 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001926 goto failed;
1927 }
1928
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001929 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1930 if (!cmd) {
1931 err = -ENOMEM;
1932 goto failed;
1933 }
1934
Johan Hedberg2b76f452013-03-15 17:07:04 -05001935 hci_req_init(&req, hdev);
1936
Johan Hedberg9a43e252013-10-20 19:00:07 +03001937 /* If BR/EDR is not enabled and we disable advertising as a
1938 * by-product of disabling connectable, we need to update the
1939 * advertising flags.
1940 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001941 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03001942 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001943 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
1944 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03001945 }
1946 update_adv_data(&req);
1947 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001948 if (cp->val) {
1949 scan = SCAN_PAGE;
1950 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001951 /* If we don't have any whitelist entries just
1952 * disable all scanning. If there are entries
1953 * and we had both page and inquiry scanning
1954 * enabled then fall back to only page scanning.
1955 * Otherwise no changes are needed.
1956 */
1957 if (list_empty(&hdev->whitelist))
1958 scan = SCAN_DISABLED;
1959 else if (test_bit(HCI_ISCAN, &hdev->flags))
1960 scan = SCAN_PAGE;
1961 else
1962 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001963
1964 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001965 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001966 cancel_delayed_work(&hdev->discov_off);
1967 }
1968
1969 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1970 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001971
Johan Hedberg3bd27242014-07-28 20:53:58 +03001972no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03001973 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001974 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001975 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001976
Johan Hedberg2b76f452013-03-15 17:07:04 -05001977 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001978 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001979 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001980 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001981 err = set_connectable_update_settings(hdev, sk,
1982 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001983 goto failed;
1984 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001985
1986failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001987 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001988 return err;
1989}
1990
Johan Hedbergb2939472014-07-30 09:22:23 +03001991static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001992 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001993{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001994 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001995 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001996 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001997
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001998 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001999
Johan Hedberga7e80f22013-01-09 16:05:19 +02002000 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002001 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2002 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002003
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002004 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002005
2006 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002007 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002008 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002009 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002010
Johan Hedbergb2939472014-07-30 09:22:23 +03002011 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002012 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002013 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002014
Marcel Holtmann55594352013-10-06 16:11:57 -07002015 if (changed)
2016 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002017
Marcel Holtmann55594352013-10-06 16:11:57 -07002018unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002019 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002020 return err;
2021}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002022
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002023static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2024 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002025{
2026 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002027 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002028 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002029 int err;
2030
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002031 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032
Johan Hedberge6fe7982013-10-02 15:45:22 +03002033 status = mgmt_bredr_support(hdev);
2034 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002035 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2036 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002037
Johan Hedberga7e80f22013-01-09 16:05:19 +02002038 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002039 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2040 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002041
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002042 hci_dev_lock(hdev);
2043
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002044 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002045 bool changed = false;
2046
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002047 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002048 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002049 changed = true;
2050 }
2051
2052 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2053 if (err < 0)
2054 goto failed;
2055
2056 if (changed)
2057 err = new_settings(hdev, sk);
2058
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002059 goto failed;
2060 }
2061
2062 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002063 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2064 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002065 goto failed;
2066 }
2067
2068 val = !!cp->val;
2069
2070 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2071 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2072 goto failed;
2073 }
2074
2075 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2076 if (!cmd) {
2077 err = -ENOMEM;
2078 goto failed;
2079 }
2080
2081 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2082 if (err < 0) {
2083 mgmt_pending_remove(cmd);
2084 goto failed;
2085 }
2086
2087failed:
2088 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002089 return err;
2090}
2091
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002092static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002093{
2094 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002095 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002096 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002097 int err;
2098
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002099 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002100
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002101 status = mgmt_bredr_support(hdev);
2102 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002103 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002104
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002105 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002106 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2107 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002108
Johan Hedberga7e80f22013-01-09 16:05:19 +02002109 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002110 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2111 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002112
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002113 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002114
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002115 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002116 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002117
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002118 if (cp->val) {
2119 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2120 &hdev->dev_flags);
2121 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002122 changed = hci_dev_test_and_clear_flag(hdev,
2123 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002124 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002125 changed = hci_dev_test_and_clear_flag(hdev,
2126 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002127 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002128 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002129 }
2130
2131 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2132 if (err < 0)
2133 goto failed;
2134
2135 if (changed)
2136 err = new_settings(hdev, sk);
2137
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002138 goto failed;
2139 }
2140
Johan Hedberg94d52da2015-02-19 17:38:06 +02002141 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002142 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2143 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002144 goto failed;
2145 }
2146
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002147 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002148 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2149 goto failed;
2150 }
2151
2152 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2153 if (!cmd) {
2154 err = -ENOMEM;
2155 goto failed;
2156 }
2157
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002158 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002159 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2160 sizeof(cp->val), &cp->val);
2161
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002162 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002163 if (err < 0) {
2164 mgmt_pending_remove(cmd);
2165 goto failed;
2166 }
2167
2168failed:
2169 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002170 return err;
2171}
2172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002173static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002174{
2175 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002176 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002177 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002178 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002180 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002181
Johan Hedberge6fe7982013-10-02 15:45:22 +03002182 status = mgmt_bredr_support(hdev);
2183 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002184 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002185
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002186 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002187 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2188 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002189
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002190 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002191 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2192 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002193
Johan Hedberga7e80f22013-01-09 16:05:19 +02002194 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002195 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2196 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002197
Marcel Holtmannee392692013-10-01 22:59:23 -07002198 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002199
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002200 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002201 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2202 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002203 goto unlock;
2204 }
2205
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002206 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002207 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002208 } else {
2209 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002210 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2211 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002212 goto unlock;
2213 }
2214
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002215 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002216 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002217
2218 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2219 if (err < 0)
2220 goto unlock;
2221
2222 if (changed)
2223 err = new_settings(hdev, sk);
2224
2225unlock:
2226 hci_dev_unlock(hdev);
2227 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002228}
2229
Marcel Holtmann1904a852015-01-11 13:50:44 -08002230static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002231{
2232 struct cmd_lookup match = { NULL, hdev };
2233
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302234 hci_dev_lock(hdev);
2235
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002236 if (status) {
2237 u8 mgmt_err = mgmt_status(status);
2238
2239 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2240 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302241 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002242 }
2243
2244 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2245
2246 new_settings(hdev, match.sk);
2247
2248 if (match.sk)
2249 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002250
2251 /* Make sure the controller has a good default for
2252 * advertising data. Restrict the update to when LE
2253 * has actually been enabled. During power on, the
2254 * update in powered_update_hci will take care of it.
2255 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002256 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002257 struct hci_request req;
2258
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002259 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002260 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002261 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002262 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002263 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002264 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302265
2266unlock:
2267 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002268}
2269
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002270static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002271{
2272 struct mgmt_mode *cp = data;
2273 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002274 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002275 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002276 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002277 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002278
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002279 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002280
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002281 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002282 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2283 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002284
Johan Hedberga7e80f22013-01-09 16:05:19 +02002285 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002286 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2287 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002288
Johan Hedbergc73eee92013-04-19 18:35:21 +03002289 /* LE-only devices do not allow toggling LE on/off */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002290 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002291 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2292 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002293
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002294 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295
2296 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002297 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002298
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002299 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002300 bool changed = false;
2301
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002302 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002303 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002304 changed = true;
2305 }
2306
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002307 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002308 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002309 changed = true;
2310 }
2311
Johan Hedberg06199cf2012-02-22 16:37:11 +02002312 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2313 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002314 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002315
2316 if (changed)
2317 err = new_settings(hdev, sk);
2318
Johan Hedberg1de028c2012-02-29 19:55:35 -08002319 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002320 }
2321
Johan Hedberg4375f102013-09-25 13:26:10 +03002322 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2323 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002324 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2325 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002326 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002327 }
2328
2329 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2330 if (!cmd) {
2331 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002332 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002333 }
2334
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002335 hci_req_init(&req, hdev);
2336
Johan Hedberg06199cf2012-02-22 16:37:11 +02002337 memset(&hci_cp, 0, sizeof(hci_cp));
2338
2339 if (val) {
2340 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002341 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002342 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002343 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002344 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002345 }
2346
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002347 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2348 &hci_cp);
2349
2350 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302351 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002352 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002353
Johan Hedberg1de028c2012-02-29 19:55:35 -08002354unlock:
2355 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002356 return err;
2357}
2358
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002359/* This is a helper function to test for pending mgmt commands that can
2360 * cause CoD or EIR HCI commands. We can only allow one such pending
2361 * mgmt command at a time since otherwise we cannot easily track what
2362 * the current values are, will be, and based on that calculate if a new
2363 * HCI command needs to be sent and if yes with what value.
2364 */
2365static bool pending_eir_or_class(struct hci_dev *hdev)
2366{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002367 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002368
2369 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2370 switch (cmd->opcode) {
2371 case MGMT_OP_ADD_UUID:
2372 case MGMT_OP_REMOVE_UUID:
2373 case MGMT_OP_SET_DEV_CLASS:
2374 case MGMT_OP_SET_POWERED:
2375 return true;
2376 }
2377 }
2378
2379 return false;
2380}
2381
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002382static const u8 bluetooth_base_uuid[] = {
2383 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2384 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2385};
2386
2387static u8 get_uuid_size(const u8 *uuid)
2388{
2389 u32 val;
2390
2391 if (memcmp(uuid, bluetooth_base_uuid, 12))
2392 return 128;
2393
2394 val = get_unaligned_le32(&uuid[12]);
2395 if (val > 0xffff)
2396 return 32;
2397
2398 return 16;
2399}
2400
Johan Hedberg92da6092013-03-15 17:06:55 -05002401static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2402{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002403 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002404
2405 hci_dev_lock(hdev);
2406
2407 cmd = mgmt_pending_find(mgmt_op, hdev);
2408 if (!cmd)
2409 goto unlock;
2410
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002411 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2412 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002413
2414 mgmt_pending_remove(cmd);
2415
2416unlock:
2417 hci_dev_unlock(hdev);
2418}
2419
Marcel Holtmann1904a852015-01-11 13:50:44 -08002420static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002421{
2422 BT_DBG("status 0x%02x", status);
2423
2424 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2425}
2426
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002427static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002428{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002429 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002430 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002431 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002432 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002433 int err;
2434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002435 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002436
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002437 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002438
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002439 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002440 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2441 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002442 goto failed;
2443 }
2444
Andre Guedes92c4c202012-06-07 19:05:44 -03002445 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002446 if (!uuid) {
2447 err = -ENOMEM;
2448 goto failed;
2449 }
2450
2451 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002452 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002453 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002454
Johan Hedbergde66aa62013-01-27 00:31:27 +02002455 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002456
Johan Hedberg890ea892013-03-15 17:06:52 -05002457 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002458
Johan Hedberg890ea892013-03-15 17:06:52 -05002459 update_class(&req);
2460 update_eir(&req);
2461
Johan Hedberg92da6092013-03-15 17:06:55 -05002462 err = hci_req_run(&req, add_uuid_complete);
2463 if (err < 0) {
2464 if (err != -ENODATA)
2465 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002466
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002467 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2468 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002469 goto failed;
2470 }
2471
2472 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002473 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002474 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002475 goto failed;
2476 }
2477
2478 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002479
2480failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002481 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 return err;
2483}
2484
Johan Hedberg24b78d02012-02-23 23:24:30 +02002485static bool enable_service_cache(struct hci_dev *hdev)
2486{
2487 if (!hdev_is_powered(hdev))
2488 return false;
2489
2490 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002491 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2492 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002493 return true;
2494 }
2495
2496 return false;
2497}
2498
Marcel Holtmann1904a852015-01-11 13:50:44 -08002499static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002500{
2501 BT_DBG("status 0x%02x", status);
2502
2503 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2504}
2505
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002506static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002507 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002508{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002509 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002510 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002511 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002512 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 -05002513 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 int err, found;
2515
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002516 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002517
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002518 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002519
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002520 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002521 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2522 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002523 goto unlock;
2524 }
2525
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002526 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002527 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002528
Johan Hedberg24b78d02012-02-23 23:24:30 +02002529 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002530 err = mgmt_cmd_complete(sk, hdev->id,
2531 MGMT_OP_REMOVE_UUID,
2532 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002533 goto unlock;
2534 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002535
Johan Hedberg9246a862012-02-23 21:33:16 +02002536 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002537 }
2538
2539 found = 0;
2540
Johan Hedberg056341c2013-01-27 00:31:30 +02002541 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002542 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2543 continue;
2544
2545 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002546 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002547 found++;
2548 }
2549
2550 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002551 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2552 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002553 goto unlock;
2554 }
2555
Johan Hedberg9246a862012-02-23 21:33:16 +02002556update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002557 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002558
Johan Hedberg890ea892013-03-15 17:06:52 -05002559 update_class(&req);
2560 update_eir(&req);
2561
Johan Hedberg92da6092013-03-15 17:06:55 -05002562 err = hci_req_run(&req, remove_uuid_complete);
2563 if (err < 0) {
2564 if (err != -ENODATA)
2565 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002566
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002567 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2568 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002569 goto unlock;
2570 }
2571
2572 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002573 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002574 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002575 goto unlock;
2576 }
2577
2578 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002579
2580unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002581 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002582 return err;
2583}
2584
Marcel Holtmann1904a852015-01-11 13:50:44 -08002585static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002586{
2587 BT_DBG("status 0x%02x", status);
2588
2589 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2590}
2591
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002593 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002594{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002595 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002596 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002597 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002598 int err;
2599
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002600 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002601
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002602 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002603 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2604 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002605
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002606 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002607
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002608 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002609 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2610 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002611 goto unlock;
2612 }
2613
2614 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002615 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2616 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002617 goto unlock;
2618 }
2619
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002620 hdev->major_class = cp->major;
2621 hdev->minor_class = cp->minor;
2622
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002623 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002624 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2625 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002626 goto unlock;
2627 }
2628
Johan Hedberg890ea892013-03-15 17:06:52 -05002629 hci_req_init(&req, hdev);
2630
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002631 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002632 hci_dev_unlock(hdev);
2633 cancel_delayed_work_sync(&hdev->service_cache);
2634 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002635 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002636 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002637
Johan Hedberg890ea892013-03-15 17:06:52 -05002638 update_class(&req);
2639
Johan Hedberg92da6092013-03-15 17:06:55 -05002640 err = hci_req_run(&req, set_class_complete);
2641 if (err < 0) {
2642 if (err != -ENODATA)
2643 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002644
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002645 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2646 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002647 goto unlock;
2648 }
2649
2650 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002651 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002652 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002653 goto unlock;
2654 }
2655
2656 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002657
Johan Hedbergb5235a62012-02-21 14:32:24 +02002658unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002659 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002660 return err;
2661}
2662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002663static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002664 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002665{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002666 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002667 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2668 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002669 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002670 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002671 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002672
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002673 BT_DBG("request for %s", hdev->name);
2674
2675 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002676 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2677 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002678
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002679 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002680 if (key_count > max_key_count) {
2681 BT_ERR("load_link_keys: too big key_count value %u",
2682 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002683 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2684 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002685 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002686
Johan Hedberg86742e12011-11-07 23:13:38 +02002687 expected_len = sizeof(*cp) + key_count *
2688 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002689 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002690 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002691 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002692 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2693 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694 }
2695
Johan Hedberg4ae14302013-01-20 14:27:13 +02002696 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002697 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2698 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002699
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002700 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002701 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002703 for (i = 0; i < key_count; i++) {
2704 struct mgmt_link_key_info *key = &cp->keys[i];
2705
Marcel Holtmann8e991132014-01-10 02:07:25 -08002706 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002707 return mgmt_cmd_status(sk, hdev->id,
2708 MGMT_OP_LOAD_LINK_KEYS,
2709 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002710 }
2711
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002712 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002713
2714 hci_link_keys_clear(hdev);
2715
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002716 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002717 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2718 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002719 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002720 changed = hci_dev_test_and_clear_flag(hdev,
2721 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002722
2723 if (changed)
2724 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002725
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002726 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002727 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002728
Johan Hedberg58e92932014-06-24 14:00:26 +03002729 /* Always ignore debug keys and require a new pairing if
2730 * the user wants to use them.
2731 */
2732 if (key->type == HCI_LK_DEBUG_COMBINATION)
2733 continue;
2734
Johan Hedberg7652ff62014-06-24 13:15:49 +03002735 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2736 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002737 }
2738
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002739 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002740
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002741 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002742
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002743 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002744}
2745
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002746static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002747 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002748{
2749 struct mgmt_ev_device_unpaired ev;
2750
2751 bacpy(&ev.addr.bdaddr, bdaddr);
2752 ev.addr.type = addr_type;
2753
2754 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002755 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002756}
2757
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002758static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002759 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002760{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002761 struct mgmt_cp_unpair_device *cp = data;
2762 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002763 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002764 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002765 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002766 int err;
2767
Johan Hedberga8a1d192011-11-10 15:54:38 +02002768 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002769 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2770 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002771
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002772 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002773 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2774 MGMT_STATUS_INVALID_PARAMS,
2775 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002776
Johan Hedberg118da702013-01-20 14:27:20 +02002777 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002778 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2779 MGMT_STATUS_INVALID_PARAMS,
2780 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002781
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002782 hci_dev_lock(hdev);
2783
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002784 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002785 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2786 MGMT_STATUS_NOT_POWERED, &rp,
2787 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002788 goto unlock;
2789 }
2790
Johan Hedberge0b2b272014-02-18 17:14:31 +02002791 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002792 /* If disconnection is requested, then look up the
2793 * connection. If the remote device is connected, it
2794 * will be later used to terminate the link.
2795 *
2796 * Setting it to NULL explicitly will cause no
2797 * termination of the link.
2798 */
2799 if (cp->disconnect)
2800 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2801 &cp->addr.bdaddr);
2802 else
2803 conn = NULL;
2804
Johan Hedberg124f6e32012-02-09 13:50:12 +02002805 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002806 } else {
2807 u8 addr_type;
2808
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002809 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2810 &cp->addr.bdaddr);
2811 if (conn) {
2812 /* Defer clearing up the connection parameters
2813 * until closing to give a chance of keeping
2814 * them if a repairing happens.
2815 */
2816 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2817
2818 /* If disconnection is not requested, then
2819 * clear the connection variable so that the
2820 * link is not terminated.
2821 */
2822 if (!cp->disconnect)
2823 conn = NULL;
2824 }
2825
Johan Hedberge0b2b272014-02-18 17:14:31 +02002826 if (cp->addr.type == BDADDR_LE_PUBLIC)
2827 addr_type = ADDR_LE_DEV_PUBLIC;
2828 else
2829 addr_type = ADDR_LE_DEV_RANDOM;
2830
Johan Hedberga7ec7332014-02-18 17:14:35 +02002831 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2832
Johan Hedberge0b2b272014-02-18 17:14:31 +02002833 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2834 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002835
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002836 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002837 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2838 MGMT_STATUS_NOT_PAIRED, &rp,
2839 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002840 goto unlock;
2841 }
2842
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002843 /* If the connection variable is set, then termination of the
2844 * link is requested.
2845 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002846 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002847 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2848 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002849 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002850 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002851 }
2852
Johan Hedberg124f6e32012-02-09 13:50:12 +02002853 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002854 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002855 if (!cmd) {
2856 err = -ENOMEM;
2857 goto unlock;
2858 }
2859
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002860 cmd->cmd_complete = addr_cmd_complete;
2861
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002862 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002863 dc.reason = 0x13; /* Remote User Terminated Connection */
2864 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2865 if (err < 0)
2866 mgmt_pending_remove(cmd);
2867
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002868unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002869 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002870 return err;
2871}
2872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002873static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002874 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002875{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002876 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002877 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002878 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002879 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002880 int err;
2881
2882 BT_DBG("");
2883
Johan Hedberg06a63b12013-01-20 14:27:21 +02002884 memset(&rp, 0, sizeof(rp));
2885 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2886 rp.addr.type = cp->addr.type;
2887
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002888 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002889 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2890 MGMT_STATUS_INVALID_PARAMS,
2891 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002892
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002893 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002894
2895 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002896 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2897 MGMT_STATUS_NOT_POWERED, &rp,
2898 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002899 goto failed;
2900 }
2901
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002902 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002903 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2904 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002905 goto failed;
2906 }
2907
Andre Guedes591f47f2012-04-24 21:02:49 -03002908 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002909 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2910 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002911 else
2912 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002913
Vishal Agarwalf9607272012-06-13 05:32:43 +05302914 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002915 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2916 MGMT_STATUS_NOT_CONNECTED, &rp,
2917 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002918 goto failed;
2919 }
2920
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002921 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002922 if (!cmd) {
2923 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002924 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002925 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002926
Johan Hedbergf5818c22014-12-05 13:36:02 +02002927 cmd->cmd_complete = generic_cmd_complete;
2928
Johan Hedberge3f2f922014-08-18 20:33:33 +03002929 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002930 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002931 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002932
2933failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002934 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002935 return err;
2936}
2937
Andre Guedes57c14772012-04-24 21:02:50 -03002938static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002939{
2940 switch (link_type) {
2941 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002942 switch (addr_type) {
2943 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002944 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002945
Johan Hedberg48264f02011-11-09 13:58:58 +02002946 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002947 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002948 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002949 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002950
Johan Hedberg4c659c32011-11-07 23:13:39 +02002951 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002952 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002953 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002954 }
2955}
2956
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002957static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2958 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002959{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002960 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002961 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002962 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002963 int err;
2964 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002965
2966 BT_DBG("");
2967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002968 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002969
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002970 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002971 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2972 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002973 goto unlock;
2974 }
2975
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002976 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002977 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2978 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002979 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002980 }
2981
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002982 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002983 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002984 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002985 err = -ENOMEM;
2986 goto unlock;
2987 }
2988
Johan Hedberg2784eb42011-01-21 13:56:35 +02002989 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002990 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002991 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2992 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002993 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002994 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002995 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002996 continue;
2997 i++;
2998 }
2999
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003000 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003001
Johan Hedberg4c659c32011-11-07 23:13:39 +02003002 /* Recalculate length in case of filtered SCO connections, etc */
3003 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003004
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003005 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3006 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003007
Johan Hedberga38528f2011-01-22 06:46:43 +02003008 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003009
3010unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003011 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003012 return err;
3013}
3014
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003015static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003016 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003017{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003018 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003019 int err;
3020
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003021 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003022 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003023 if (!cmd)
3024 return -ENOMEM;
3025
Johan Hedbergd8457692012-02-17 14:24:57 +02003026 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003027 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003028 if (err < 0)
3029 mgmt_pending_remove(cmd);
3030
3031 return err;
3032}
3033
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003034static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003035 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003036{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003037 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003038 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003039 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003040 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003041 int err;
3042
3043 BT_DBG("");
3044
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003045 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003046
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003047 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003048 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3049 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003050 goto failed;
3051 }
3052
Johan Hedbergd8457692012-02-17 14:24:57 +02003053 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003054 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003055 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3056 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003057 goto failed;
3058 }
3059
3060 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003061 struct mgmt_cp_pin_code_neg_reply ncp;
3062
3063 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003064
3065 BT_ERR("PIN code is not 16 bytes long");
3066
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003067 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003068 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003069 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3070 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003071
3072 goto failed;
3073 }
3074
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003075 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003076 if (!cmd) {
3077 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003078 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003079 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003080
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003081 cmd->cmd_complete = addr_cmd_complete;
3082
Johan Hedbergd8457692012-02-17 14:24:57 +02003083 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003084 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003085 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003086
3087 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3088 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003089 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003090
3091failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003092 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003093 return err;
3094}
3095
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003096static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3097 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003098{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003099 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003100
3101 BT_DBG("");
3102
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003103 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003104 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3105 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003106
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003107 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003108
3109 hdev->io_capability = cp->io_capability;
3110
3111 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003112 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003113
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003114 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003115
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003116 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3117 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003118}
3119
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003120static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003121{
3122 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003123 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003124
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003125 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003126 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3127 continue;
3128
Johan Hedberge9a416b2011-02-19 12:05:56 -03003129 if (cmd->user_data != conn)
3130 continue;
3131
3132 return cmd;
3133 }
3134
3135 return NULL;
3136}
3137
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003138static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003139{
3140 struct mgmt_rp_pair_device rp;
3141 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003142 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003143
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003144 bacpy(&rp.addr.bdaddr, &conn->dst);
3145 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003146
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003147 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3148 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003149
3150 /* So we don't get further callbacks for this connection */
3151 conn->connect_cfm_cb = NULL;
3152 conn->security_cfm_cb = NULL;
3153 conn->disconn_cfm_cb = NULL;
3154
David Herrmann76a68ba2013-04-06 20:28:37 +02003155 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003156
3157 /* The device is paired so there is no need to remove
3158 * its connection parameters anymore.
3159 */
3160 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003161
3162 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003163
3164 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003165}
3166
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003167void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3168{
3169 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003170 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003171
3172 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003173 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003174 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003175 mgmt_pending_remove(cmd);
3176 }
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003177}
3178
Johan Hedberge9a416b2011-02-19 12:05:56 -03003179static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3180{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003181 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003182
3183 BT_DBG("status %u", status);
3184
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003185 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003186 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003187 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003188 return;
3189 }
3190
3191 cmd->cmd_complete(cmd, mgmt_status(status));
3192 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003193}
3194
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003195static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303196{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003197 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303198
3199 BT_DBG("status %u", status);
3200
3201 if (!status)
3202 return;
3203
3204 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003205 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303206 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003207 return;
3208 }
3209
3210 cmd->cmd_complete(cmd, mgmt_status(status));
3211 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303212}
3213
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003214static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003215 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003216{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003217 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003218 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003219 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003220 u8 sec_level, auth_type;
3221 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003222 int err;
3223
3224 BT_DBG("");
3225
Szymon Jancf950a30e2013-01-18 12:48:07 +01003226 memset(&rp, 0, sizeof(rp));
3227 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3228 rp.addr.type = cp->addr.type;
3229
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003230 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003231 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3232 MGMT_STATUS_INVALID_PARAMS,
3233 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003234
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003235 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003236 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3237 MGMT_STATUS_INVALID_PARAMS,
3238 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003239
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003240 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003241
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003242 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003243 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3244 MGMT_STATUS_NOT_POWERED, &rp,
3245 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003246 goto unlock;
3247 }
3248
Johan Hedberg55e76b32015-03-10 22:34:40 +02003249 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3250 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3251 MGMT_STATUS_ALREADY_PAIRED, &rp,
3252 sizeof(rp));
3253 goto unlock;
3254 }
3255
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003256 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003257 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003258
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003259 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003260 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3261 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003262 } else {
3263 u8 addr_type;
3264
3265 /* Convert from L2CAP channel address type to HCI address type
3266 */
3267 if (cp->addr.type == BDADDR_LE_PUBLIC)
3268 addr_type = ADDR_LE_DEV_PUBLIC;
3269 else
3270 addr_type = ADDR_LE_DEV_RANDOM;
3271
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003272 /* When pairing a new device, it is expected to remember
3273 * this device for future connections. Adding the connection
3274 * parameter information ahead of time allows tracking
3275 * of the slave preferred values and will speed up any
3276 * further connection establishment.
3277 *
3278 * If connection parameters already exist, then they
3279 * will be kept and this function does nothing.
3280 */
3281 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3282
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003283 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003284 sec_level, HCI_LE_CONN_TIMEOUT,
3285 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003286 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003287
Ville Tervo30e76272011-02-22 16:10:53 -03003288 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003289 int status;
3290
3291 if (PTR_ERR(conn) == -EBUSY)
3292 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003293 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3294 status = MGMT_STATUS_NOT_SUPPORTED;
3295 else if (PTR_ERR(conn) == -ECONNREFUSED)
3296 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003297 else
3298 status = MGMT_STATUS_CONNECT_FAILED;
3299
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003300 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3301 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003302 goto unlock;
3303 }
3304
3305 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003306 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003307 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3308 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003309 goto unlock;
3310 }
3311
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003312 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003313 if (!cmd) {
3314 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003315 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003316 goto unlock;
3317 }
3318
Johan Hedberg04ab2742014-12-05 13:36:04 +02003319 cmd->cmd_complete = pairing_complete;
3320
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003321 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003322 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003323 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407be2014-02-18 21:41:34 +02003324 conn->security_cfm_cb = pairing_complete_cb;
3325 conn->disconn_cfm_cb = pairing_complete_cb;
3326 } else {
3327 conn->connect_cfm_cb = le_pairing_complete_cb;
3328 conn->security_cfm_cb = le_pairing_complete_cb;
3329 conn->disconn_cfm_cb = le_pairing_complete_cb;
3330 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003331
Johan Hedberge9a416b2011-02-19 12:05:56 -03003332 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003333 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003334
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003335 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003336 hci_conn_security(conn, sec_level, auth_type, true)) {
3337 cmd->cmd_complete(cmd, 0);
3338 mgmt_pending_remove(cmd);
3339 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003340
3341 err = 0;
3342
3343unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003344 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003345 return err;
3346}
3347
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003348static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3349 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003350{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003351 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003352 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003353 struct hci_conn *conn;
3354 int err;
3355
3356 BT_DBG("");
3357
Johan Hedberg28424702012-02-02 04:02:29 +02003358 hci_dev_lock(hdev);
3359
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003360 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003361 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3362 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003363 goto unlock;
3364 }
3365
Johan Hedberg28424702012-02-02 04:02:29 +02003366 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3367 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003368 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3369 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003370 goto unlock;
3371 }
3372
3373 conn = cmd->user_data;
3374
3375 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003376 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3377 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003378 goto unlock;
3379 }
3380
Johan Hedberga511b352014-12-11 21:45:45 +02003381 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3382 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003383
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003384 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3385 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003386unlock:
3387 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003388 return err;
3389}
3390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003391static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003392 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003393 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003394{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003395 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003396 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003397 int err;
3398
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003399 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003400
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003401 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003402 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3403 MGMT_STATUS_NOT_POWERED, addr,
3404 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003405 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003406 }
3407
Johan Hedberg1707c602013-03-15 17:07:15 -05003408 if (addr->type == BDADDR_BREDR)
3409 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003410 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003411 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003412
Johan Hedberg272d90d2012-02-09 15:26:12 +02003413 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003414 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3415 MGMT_STATUS_NOT_CONNECTED, addr,
3416 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003417 goto done;
3418 }
3419
Johan Hedberg1707c602013-03-15 17:07:15 -05003420 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003421 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003422 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003423 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3424 MGMT_STATUS_SUCCESS, addr,
3425 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003426 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003427 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3428 MGMT_STATUS_FAILED, addr,
3429 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003430
Brian Gix47c15e22011-11-16 13:53:14 -08003431 goto done;
3432 }
3433
Johan Hedberg1707c602013-03-15 17:07:15 -05003434 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003435 if (!cmd) {
3436 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003437 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003438 }
3439
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003440 cmd->cmd_complete = addr_cmd_complete;
3441
Brian Gix0df4c182011-11-16 13:53:13 -08003442 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003443 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3444 struct hci_cp_user_passkey_reply cp;
3445
Johan Hedberg1707c602013-03-15 17:07:15 -05003446 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003447 cp.passkey = passkey;
3448 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3449 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003450 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3451 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003452
Johan Hedberga664b5b2011-02-19 12:06:02 -03003453 if (err < 0)
3454 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003455
Brian Gix0df4c182011-11-16 13:53:13 -08003456done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003457 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003458 return err;
3459}
3460
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303461static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3462 void *data, u16 len)
3463{
3464 struct mgmt_cp_pin_code_neg_reply *cp = data;
3465
3466 BT_DBG("");
3467
Johan Hedberg1707c602013-03-15 17:07:15 -05003468 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303469 MGMT_OP_PIN_CODE_NEG_REPLY,
3470 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3471}
3472
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003473static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3474 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003475{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003476 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003477
3478 BT_DBG("");
3479
3480 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003481 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3482 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003483
Johan Hedberg1707c602013-03-15 17:07:15 -05003484 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003485 MGMT_OP_USER_CONFIRM_REPLY,
3486 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003487}
3488
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003489static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003490 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003491{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003492 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003493
3494 BT_DBG("");
3495
Johan Hedberg1707c602013-03-15 17:07:15 -05003496 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003497 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3498 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003499}
3500
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003501static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3502 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003503{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003504 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003505
3506 BT_DBG("");
3507
Johan Hedberg1707c602013-03-15 17:07:15 -05003508 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003509 MGMT_OP_USER_PASSKEY_REPLY,
3510 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003511}
3512
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003513static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003514 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003515{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003516 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003517
3518 BT_DBG("");
3519
Johan Hedberg1707c602013-03-15 17:07:15 -05003520 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003521 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3522 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003523}
3524
Johan Hedberg13928972013-03-15 17:07:00 -05003525static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003526{
Johan Hedberg13928972013-03-15 17:07:00 -05003527 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003528 struct hci_cp_write_local_name cp;
3529
Johan Hedberg13928972013-03-15 17:07:00 -05003530 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003531
Johan Hedberg890ea892013-03-15 17:06:52 -05003532 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003533}
3534
Marcel Holtmann1904a852015-01-11 13:50:44 -08003535static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003536{
3537 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003538 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003539
3540 BT_DBG("status 0x%02x", status);
3541
3542 hci_dev_lock(hdev);
3543
3544 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3545 if (!cmd)
3546 goto unlock;
3547
3548 cp = cmd->param;
3549
3550 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003551 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3552 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003553 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003554 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3555 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003556
3557 mgmt_pending_remove(cmd);
3558
3559unlock:
3560 hci_dev_unlock(hdev);
3561}
3562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003563static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003564 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003565{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003566 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003567 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003568 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003569 int err;
3570
3571 BT_DBG("");
3572
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003573 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003574
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003575 /* If the old values are the same as the new ones just return a
3576 * direct command complete event.
3577 */
3578 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3579 !memcmp(hdev->short_name, cp->short_name,
3580 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003581 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3582 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003583 goto failed;
3584 }
3585
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003586 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003587
Johan Hedbergb5235a62012-02-21 14:32:24 +02003588 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003589 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003590
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003591 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3592 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003593 if (err < 0)
3594 goto failed;
3595
3596 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003597 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003598
Johan Hedbergb5235a62012-02-21 14:32:24 +02003599 goto failed;
3600 }
3601
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003602 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003603 if (!cmd) {
3604 err = -ENOMEM;
3605 goto failed;
3606 }
3607
Johan Hedberg13928972013-03-15 17:07:00 -05003608 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3609
Johan Hedberg890ea892013-03-15 17:06:52 -05003610 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003611
3612 if (lmp_bredr_capable(hdev)) {
3613 update_name(&req);
3614 update_eir(&req);
3615 }
3616
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003617 /* The name is stored in the scan response data and so
3618 * no need to udpate the advertising data here.
3619 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003620 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003621 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003622
Johan Hedberg13928972013-03-15 17:07:00 -05003623 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003624 if (err < 0)
3625 mgmt_pending_remove(cmd);
3626
3627failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003628 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003629 return err;
3630}
3631
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003632static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003633 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003634{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003635 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003636 int err;
3637
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003638 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003639
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003640 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003641
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003642 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003643 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3644 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003645 goto unlock;
3646 }
3647
Andre Guedes9a1a1992012-07-24 15:03:48 -03003648 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003649 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3650 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003651 goto unlock;
3652 }
3653
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003654 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003655 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3656 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003657 goto unlock;
3658 }
3659
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003660 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003661 if (!cmd) {
3662 err = -ENOMEM;
3663 goto unlock;
3664 }
3665
Johan Hedberg710f11c2014-05-26 11:21:22 +03003666 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003667 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3668 0, NULL);
3669 else
3670 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3671
Szymon Jancc35938b2011-03-22 13:12:21 +01003672 if (err < 0)
3673 mgmt_pending_remove(cmd);
3674
3675unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003676 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003677 return err;
3678}
3679
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003680static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003681 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003682{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003683 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003684 int err;
3685
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003686 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003687
Johan Hedberg5d57e792015-01-23 10:10:38 +02003688 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003689 return mgmt_cmd_complete(sk, hdev->id,
3690 MGMT_OP_ADD_REMOTE_OOB_DATA,
3691 MGMT_STATUS_INVALID_PARAMS,
3692 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003693
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003694 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003695
Marcel Holtmannec109112014-01-10 02:07:30 -08003696 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3697 struct mgmt_cp_add_remote_oob_data *cp = data;
3698 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003699
Johan Hedbergc19a4952014-11-17 20:52:19 +02003700 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003701 err = mgmt_cmd_complete(sk, hdev->id,
3702 MGMT_OP_ADD_REMOTE_OOB_DATA,
3703 MGMT_STATUS_INVALID_PARAMS,
3704 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003705 goto unlock;
3706 }
3707
Marcel Holtmannec109112014-01-10 02:07:30 -08003708 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003709 cp->addr.type, cp->hash,
3710 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003711 if (err < 0)
3712 status = MGMT_STATUS_FAILED;
3713 else
3714 status = MGMT_STATUS_SUCCESS;
3715
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003716 err = mgmt_cmd_complete(sk, hdev->id,
3717 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3718 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003719 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3720 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003721 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003722 u8 status;
3723
Johan Hedberg86df9202014-10-26 20:52:27 +01003724 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003725 /* Enforce zero-valued 192-bit parameters as
3726 * long as legacy SMP OOB isn't implemented.
3727 */
3728 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3729 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003730 err = mgmt_cmd_complete(sk, hdev->id,
3731 MGMT_OP_ADD_REMOTE_OOB_DATA,
3732 MGMT_STATUS_INVALID_PARAMS,
3733 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003734 goto unlock;
3735 }
3736
Johan Hedberg86df9202014-10-26 20:52:27 +01003737 rand192 = NULL;
3738 hash192 = NULL;
3739 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003740 /* In case one of the P-192 values is set to zero,
3741 * then just disable OOB data for P-192.
3742 */
3743 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3744 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3745 rand192 = NULL;
3746 hash192 = NULL;
3747 } else {
3748 rand192 = cp->rand192;
3749 hash192 = cp->hash192;
3750 }
3751 }
3752
3753 /* In case one of the P-256 values is set to zero, then just
3754 * disable OOB data for P-256.
3755 */
3756 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3757 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3758 rand256 = NULL;
3759 hash256 = NULL;
3760 } else {
3761 rand256 = cp->rand256;
3762 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003763 }
3764
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003765 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003766 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003767 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003768 if (err < 0)
3769 status = MGMT_STATUS_FAILED;
3770 else
3771 status = MGMT_STATUS_SUCCESS;
3772
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003773 err = mgmt_cmd_complete(sk, hdev->id,
3774 MGMT_OP_ADD_REMOTE_OOB_DATA,
3775 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003776 } else {
3777 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003778 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3779 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003780 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003781
Johan Hedbergc19a4952014-11-17 20:52:19 +02003782unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003783 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003784 return err;
3785}
3786
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003787static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003788 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003789{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003790 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003791 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003792 int err;
3793
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003794 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003795
Johan Hedbergc19a4952014-11-17 20:52:19 +02003796 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003797 return mgmt_cmd_complete(sk, hdev->id,
3798 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3799 MGMT_STATUS_INVALID_PARAMS,
3800 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003801
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003802 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003803
Johan Hedbergeedbd582014-11-15 09:34:23 +02003804 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3805 hci_remote_oob_data_clear(hdev);
3806 status = MGMT_STATUS_SUCCESS;
3807 goto done;
3808 }
3809
Johan Hedberg6928a922014-10-26 20:46:09 +01003810 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003811 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003812 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003813 else
Szymon Janca6785be2012-12-13 15:11:21 +01003814 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003815
Johan Hedbergeedbd582014-11-15 09:34:23 +02003816done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003817 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3818 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003819
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003820 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003821 return err;
3822}
3823
Marcel Holtmann80190442014-12-04 11:36:36 +01003824static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003825{
Marcel Holtmann80190442014-12-04 11:36:36 +01003826 struct hci_dev *hdev = req->hdev;
3827 struct hci_cp_le_set_scan_param param_cp;
3828 struct hci_cp_le_set_scan_enable enable_cp;
3829 struct hci_cp_inquiry inq_cp;
3830 /* General inquiry access code (GIAC) */
3831 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3832 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003833 int err;
3834
Marcel Holtmann80190442014-12-04 11:36:36 +01003835 switch (hdev->discovery.type) {
3836 case DISCOV_TYPE_BREDR:
3837 *status = mgmt_bredr_support(hdev);
3838 if (*status)
3839 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003840
Marcel Holtmann80190442014-12-04 11:36:36 +01003841 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3842 *status = MGMT_STATUS_BUSY;
3843 return false;
3844 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003845
Marcel Holtmann80190442014-12-04 11:36:36 +01003846 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003847
Marcel Holtmann80190442014-12-04 11:36:36 +01003848 memset(&inq_cp, 0, sizeof(inq_cp));
3849 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3850 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3851 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3852 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003853
Marcel Holtmann80190442014-12-04 11:36:36 +01003854 case DISCOV_TYPE_LE:
3855 case DISCOV_TYPE_INTERLEAVED:
3856 *status = mgmt_le_support(hdev);
3857 if (*status)
3858 return false;
3859
3860 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003861 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003862 *status = MGMT_STATUS_NOT_SUPPORTED;
3863 return false;
3864 }
3865
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003866 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003867 /* Don't let discovery abort an outgoing
3868 * connection attempt that's using directed
3869 * advertising.
3870 */
3871 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3872 BT_CONNECT)) {
3873 *status = MGMT_STATUS_REJECTED;
3874 return false;
3875 }
3876
3877 disable_advertising(req);
3878 }
3879
3880 /* If controller is scanning, it means the background scanning
3881 * is running. Thus, we should temporarily stop it in order to
3882 * set the discovery scanning parameters.
3883 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003884 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
Marcel Holtmann80190442014-12-04 11:36:36 +01003885 hci_req_add_le_scan_disable(req);
3886
3887 memset(&param_cp, 0, sizeof(param_cp));
3888
3889 /* All active scans will be done with either a resolvable
3890 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003891 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003892 */
3893 err = hci_update_random_address(req, true, &own_addr_type);
3894 if (err < 0) {
3895 *status = MGMT_STATUS_FAILED;
3896 return false;
3897 }
3898
3899 param_cp.type = LE_SCAN_ACTIVE;
3900 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3901 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3902 param_cp.own_address_type = own_addr_type;
3903 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3904 &param_cp);
3905
3906 memset(&enable_cp, 0, sizeof(enable_cp));
3907 enable_cp.enable = LE_SCAN_ENABLE;
3908 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3909 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3910 &enable_cp);
3911 break;
3912
3913 default:
3914 *status = MGMT_STATUS_INVALID_PARAMS;
3915 return false;
3916 }
3917
3918 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003919}
3920
Marcel Holtmann1904a852015-01-11 13:50:44 -08003921static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3922 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003923{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003924 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003925 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003926
Andre Guedes7c307722013-04-30 15:29:28 -03003927 BT_DBG("status %d", status);
3928
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003929 hci_dev_lock(hdev);
3930
3931 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003932 if (!cmd)
3933 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3934
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003935 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003936 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003937 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003938 }
3939
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003940 if (status) {
3941 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3942 goto unlock;
3943 }
3944
Andre Guedes7c307722013-04-30 15:29:28 -03003945 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003946
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003947 /* If the scan involves LE scan, pick proper timeout to schedule
3948 * hdev->le_scan_disable that will stop it.
3949 */
Andre Guedes7c307722013-04-30 15:29:28 -03003950 switch (hdev->discovery.type) {
3951 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003952 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003953 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003954 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003955 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003956 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003957 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003958 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003959 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003960 default:
3961 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003962 timeout = 0;
3963 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003964 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003965
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003966 if (timeout) {
3967 /* When service discovery is used and the controller has
3968 * a strict duplicate filter, it is important to remember
3969 * the start and duration of the scan. This is required
3970 * for restarting scanning during the discovery phase.
3971 */
3972 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3973 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003974 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003975 hdev->discovery.scan_start = jiffies;
3976 hdev->discovery.scan_duration = timeout;
3977 }
3978
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003979 queue_delayed_work(hdev->workqueue,
3980 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003981 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003982
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003983unlock:
3984 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003985}
3986
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003987static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003988 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003989{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003990 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003991 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003992 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003993 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003994 int err;
3995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003996 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003997
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003998 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003999
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004000 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004001 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4002 MGMT_STATUS_NOT_POWERED,
4003 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004004 goto failed;
4005 }
4006
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004007 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004008 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004009 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4010 MGMT_STATUS_BUSY, &cp->type,
4011 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004012 goto failed;
4013 }
4014
Johan Hedberg2922a942014-12-05 13:36:06 +02004015 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004016 if (!cmd) {
4017 err = -ENOMEM;
4018 goto failed;
4019 }
4020
Johan Hedberg2922a942014-12-05 13:36:06 +02004021 cmd->cmd_complete = generic_cmd_complete;
4022
Marcel Holtmann22078802014-12-05 11:45:22 +01004023 /* Clear the discovery filter first to free any previously
4024 * allocated memory for the UUID list.
4025 */
4026 hci_discovery_filter_clear(hdev);
4027
Andre Guedes4aab14e2012-02-17 20:39:36 -03004028 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004029 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004030
Andre Guedes7c307722013-04-30 15:29:28 -03004031 hci_req_init(&req, hdev);
4032
Marcel Holtmann80190442014-12-04 11:36:36 +01004033 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004034 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4035 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004036 mgmt_pending_remove(cmd);
4037 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004038 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004039
Andre Guedes7c307722013-04-30 15:29:28 -03004040 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004041 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004042 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004043 goto failed;
4044 }
4045
4046 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004047
4048failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004049 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004050 return err;
4051}
4052
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004053static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4054 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004055{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004056 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4057 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004058}
4059
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004060static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4061 void *data, u16 len)
4062{
4063 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004064 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004065 struct hci_request req;
4066 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4067 u16 uuid_count, expected_len;
4068 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004069 int err;
4070
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004071 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004072
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004073 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004074
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004075 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004076 err = mgmt_cmd_complete(sk, hdev->id,
4077 MGMT_OP_START_SERVICE_DISCOVERY,
4078 MGMT_STATUS_NOT_POWERED,
4079 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004080 goto failed;
4081 }
4082
4083 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004084 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004085 err = mgmt_cmd_complete(sk, hdev->id,
4086 MGMT_OP_START_SERVICE_DISCOVERY,
4087 MGMT_STATUS_BUSY, &cp->type,
4088 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004089 goto failed;
4090 }
4091
4092 uuid_count = __le16_to_cpu(cp->uuid_count);
4093 if (uuid_count > max_uuid_count) {
4094 BT_ERR("service_discovery: too big uuid_count value %u",
4095 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004096 err = mgmt_cmd_complete(sk, hdev->id,
4097 MGMT_OP_START_SERVICE_DISCOVERY,
4098 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4099 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004100 goto failed;
4101 }
4102
4103 expected_len = sizeof(*cp) + uuid_count * 16;
4104 if (expected_len != len) {
4105 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4106 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004107 err = mgmt_cmd_complete(sk, hdev->id,
4108 MGMT_OP_START_SERVICE_DISCOVERY,
4109 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4110 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004111 goto failed;
4112 }
4113
4114 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004115 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004116 if (!cmd) {
4117 err = -ENOMEM;
4118 goto failed;
4119 }
4120
Johan Hedberg2922a942014-12-05 13:36:06 +02004121 cmd->cmd_complete = service_discovery_cmd_complete;
4122
Marcel Holtmann22078802014-12-05 11:45:22 +01004123 /* Clear the discovery filter first to free any previously
4124 * allocated memory for the UUID list.
4125 */
4126 hci_discovery_filter_clear(hdev);
4127
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004128 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004129 hdev->discovery.type = cp->type;
4130 hdev->discovery.rssi = cp->rssi;
4131 hdev->discovery.uuid_count = uuid_count;
4132
4133 if (uuid_count > 0) {
4134 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4135 GFP_KERNEL);
4136 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004137 err = mgmt_cmd_complete(sk, hdev->id,
4138 MGMT_OP_START_SERVICE_DISCOVERY,
4139 MGMT_STATUS_FAILED,
4140 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004141 mgmt_pending_remove(cmd);
4142 goto failed;
4143 }
4144 }
4145
4146 hci_req_init(&req, hdev);
4147
4148 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004149 err = mgmt_cmd_complete(sk, hdev->id,
4150 MGMT_OP_START_SERVICE_DISCOVERY,
4151 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004152 mgmt_pending_remove(cmd);
4153 goto failed;
4154 }
4155
4156 err = hci_req_run(&req, start_discovery_complete);
4157 if (err < 0) {
4158 mgmt_pending_remove(cmd);
4159 goto failed;
4160 }
4161
4162 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4163
4164failed:
4165 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004166 return err;
4167}
4168
Marcel Holtmann1904a852015-01-11 13:50:44 -08004169static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004170{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004171 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004172
Andre Guedes0e05bba2013-04-30 15:29:33 -03004173 BT_DBG("status %d", status);
4174
4175 hci_dev_lock(hdev);
4176
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004177 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4178 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004179 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004180 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004181 }
4182
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004183 if (!status)
4184 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004185
Andre Guedes0e05bba2013-04-30 15:29:33 -03004186 hci_dev_unlock(hdev);
4187}
4188
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004189static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004190 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004191{
Johan Hedbergd9306502012-02-20 23:25:18 +02004192 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004193 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004194 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004195 int err;
4196
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004197 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004198
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004199 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004200
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004201 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004202 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4203 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4204 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004205 goto unlock;
4206 }
4207
4208 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004209 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4210 MGMT_STATUS_INVALID_PARAMS,
4211 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004212 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004213 }
4214
Johan Hedberg2922a942014-12-05 13:36:06 +02004215 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004216 if (!cmd) {
4217 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004218 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004219 }
4220
Johan Hedberg2922a942014-12-05 13:36:06 +02004221 cmd->cmd_complete = generic_cmd_complete;
4222
Andre Guedes0e05bba2013-04-30 15:29:33 -03004223 hci_req_init(&req, hdev);
4224
Johan Hedberg21a60d32014-06-10 14:05:58 +03004225 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004226
Johan Hedberg21a60d32014-06-10 14:05:58 +03004227 err = hci_req_run(&req, stop_discovery_complete);
4228 if (!err) {
4229 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004230 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004231 }
4232
Johan Hedberg21a60d32014-06-10 14:05:58 +03004233 mgmt_pending_remove(cmd);
4234
4235 /* If no HCI commands were sent we're done */
4236 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004237 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4238 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004239 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4240 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004241
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004242unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004243 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004244 return err;
4245}
4246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004247static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004248 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004249{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004250 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004251 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004252 int err;
4253
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004254 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004255
Johan Hedberg561aafb2012-01-04 13:31:59 +02004256 hci_dev_lock(hdev);
4257
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004258 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004259 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4260 MGMT_STATUS_FAILED, &cp->addr,
4261 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004262 goto failed;
4263 }
4264
Johan Hedberga198e7b2012-02-17 14:27:06 +02004265 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004266 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004267 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4268 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4269 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004270 goto failed;
4271 }
4272
4273 if (cp->name_known) {
4274 e->name_state = NAME_KNOWN;
4275 list_del(&e->list);
4276 } else {
4277 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004278 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004279 }
4280
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004281 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4282 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004283
4284failed:
4285 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004286 return err;
4287}
4288
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004289static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004290 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004291{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004292 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004293 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004294 int err;
4295
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004296 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004297
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004298 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004299 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4300 MGMT_STATUS_INVALID_PARAMS,
4301 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004302
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004303 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004304
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004305 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4306 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004307 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004308 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004309 goto done;
4310 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004311
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004312 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4313 sk);
4314 status = MGMT_STATUS_SUCCESS;
4315
4316done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004317 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4318 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004319
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004320 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004321
4322 return err;
4323}
4324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004325static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004326 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004327{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004328 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004329 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004330 int err;
4331
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004332 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004333
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004334 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004335 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4336 MGMT_STATUS_INVALID_PARAMS,
4337 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004338
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004339 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004340
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004341 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4342 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004343 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004344 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004345 goto done;
4346 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004347
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004348 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4349 sk);
4350 status = MGMT_STATUS_SUCCESS;
4351
4352done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004353 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4354 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004355
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004356 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004357
4358 return err;
4359}
4360
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004361static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4362 u16 len)
4363{
4364 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004365 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004366 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004367 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004368
4369 BT_DBG("%s", hdev->name);
4370
Szymon Jancc72d4b82012-03-16 16:02:57 +01004371 source = __le16_to_cpu(cp->source);
4372
4373 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004374 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4375 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004376
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004377 hci_dev_lock(hdev);
4378
Szymon Jancc72d4b82012-03-16 16:02:57 +01004379 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004380 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4381 hdev->devid_product = __le16_to_cpu(cp->product);
4382 hdev->devid_version = __le16_to_cpu(cp->version);
4383
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004384 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4385 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004386
Johan Hedberg890ea892013-03-15 17:06:52 -05004387 hci_req_init(&req, hdev);
4388 update_eir(&req);
4389 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004390
4391 hci_dev_unlock(hdev);
4392
4393 return err;
4394}
4395
Marcel Holtmann1904a852015-01-11 13:50:44 -08004396static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4397 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004398{
4399 struct cmd_lookup match = { NULL, hdev };
4400
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304401 hci_dev_lock(hdev);
4402
Johan Hedberg4375f102013-09-25 13:26:10 +03004403 if (status) {
4404 u8 mgmt_err = mgmt_status(status);
4405
4406 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4407 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304408 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004409 }
4410
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004411 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004412 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004413 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004414 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004415
Johan Hedberg4375f102013-09-25 13:26:10 +03004416 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4417 &match);
4418
4419 new_settings(hdev, match.sk);
4420
4421 if (match.sk)
4422 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304423
4424unlock:
4425 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004426}
4427
Marcel Holtmann21b51872013-10-10 09:47:53 -07004428static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4429 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004430{
4431 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004432 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004433 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004434 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004435 int err;
4436
4437 BT_DBG("request for %s", hdev->name);
4438
Johan Hedberge6fe7982013-10-02 15:45:22 +03004439 status = mgmt_le_support(hdev);
4440 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004441 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4442 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004443
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004444 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004445 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4446 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004447
4448 hci_dev_lock(hdev);
4449
4450 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004451
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004452 /* The following conditions are ones which mean that we should
4453 * not do any HCI communication but directly send a mgmt
4454 * response to user space (after toggling the flag if
4455 * necessary).
4456 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004457 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004458 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4459 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004460 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004461 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004462 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004463 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004464
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004465 if (cp->val) {
4466 changed = !test_and_set_bit(HCI_ADVERTISING,
4467 &hdev->dev_flags);
4468 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004469 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004470 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004471 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004472 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004473 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004474 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004475 }
4476
4477 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4478 if (err < 0)
4479 goto unlock;
4480
4481 if (changed)
4482 err = new_settings(hdev, sk);
4483
4484 goto unlock;
4485 }
4486
4487 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4488 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004489 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4490 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004491 goto unlock;
4492 }
4493
4494 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4495 if (!cmd) {
4496 err = -ENOMEM;
4497 goto unlock;
4498 }
4499
4500 hci_req_init(&req, hdev);
4501
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004502 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004503 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004504 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004505 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004506
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004507 if (val)
4508 enable_advertising(&req);
4509 else
4510 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004511
4512 err = hci_req_run(&req, set_advertising_complete);
4513 if (err < 0)
4514 mgmt_pending_remove(cmd);
4515
4516unlock:
4517 hci_dev_unlock(hdev);
4518 return err;
4519}
4520
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004521static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4522 void *data, u16 len)
4523{
4524 struct mgmt_cp_set_static_address *cp = data;
4525 int err;
4526
4527 BT_DBG("%s", hdev->name);
4528
Marcel Holtmann62af4442013-10-02 22:10:32 -07004529 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004530 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4531 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004532
4533 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004534 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4535 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004536
4537 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4538 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004539 return mgmt_cmd_status(sk, hdev->id,
4540 MGMT_OP_SET_STATIC_ADDRESS,
4541 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004542
4543 /* Two most significant bits shall be set */
4544 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004545 return mgmt_cmd_status(sk, hdev->id,
4546 MGMT_OP_SET_STATIC_ADDRESS,
4547 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004548 }
4549
4550 hci_dev_lock(hdev);
4551
4552 bacpy(&hdev->static_addr, &cp->bdaddr);
4553
Marcel Holtmann93690c22015-03-06 10:11:21 -08004554 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4555 if (err < 0)
4556 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004557
Marcel Holtmann93690c22015-03-06 10:11:21 -08004558 err = new_settings(hdev, sk);
4559
4560unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004561 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004562 return err;
4563}
4564
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004565static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4566 void *data, u16 len)
4567{
4568 struct mgmt_cp_set_scan_params *cp = data;
4569 __u16 interval, window;
4570 int err;
4571
4572 BT_DBG("%s", hdev->name);
4573
4574 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004575 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4576 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004577
4578 interval = __le16_to_cpu(cp->interval);
4579
4580 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004581 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4582 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004583
4584 window = __le16_to_cpu(cp->window);
4585
4586 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004587 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4588 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004589
Marcel Holtmann899e1072013-10-14 09:55:32 -07004590 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004591 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4592 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004593
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004594 hci_dev_lock(hdev);
4595
4596 hdev->le_scan_interval = interval;
4597 hdev->le_scan_window = window;
4598
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004599 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4600 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004601
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004602 /* If background scan is running, restart it so new parameters are
4603 * loaded.
4604 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004605 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004606 hdev->discovery.state == DISCOVERY_STOPPED) {
4607 struct hci_request req;
4608
4609 hci_req_init(&req, hdev);
4610
4611 hci_req_add_le_scan_disable(&req);
4612 hci_req_add_le_passive_scan(&req);
4613
4614 hci_req_run(&req, NULL);
4615 }
4616
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004617 hci_dev_unlock(hdev);
4618
4619 return err;
4620}
4621
Marcel Holtmann1904a852015-01-11 13:50:44 -08004622static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4623 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004624{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004625 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004626
4627 BT_DBG("status 0x%02x", status);
4628
4629 hci_dev_lock(hdev);
4630
4631 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4632 if (!cmd)
4633 goto unlock;
4634
4635 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004636 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4637 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004638 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004639 struct mgmt_mode *cp = cmd->param;
4640
4641 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004642 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004643 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004644 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004645
Johan Hedberg33e38b32013-03-15 17:07:05 -05004646 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4647 new_settings(hdev, cmd->sk);
4648 }
4649
4650 mgmt_pending_remove(cmd);
4651
4652unlock:
4653 hci_dev_unlock(hdev);
4654}
4655
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004656static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004657 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004658{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004659 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004660 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004661 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004662 int err;
4663
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004664 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004665
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004666 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004667 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004668 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4669 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004670
Johan Hedberga7e80f22013-01-09 16:05:19 +02004671 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004672 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4673 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004674
Antti Julkuf6422ec2011-06-22 13:11:56 +03004675 hci_dev_lock(hdev);
4676
Johan Hedberg05cbf292013-03-15 17:07:07 -05004677 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004678 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4679 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004680 goto unlock;
4681 }
4682
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004683 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004684 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4685 hdev);
4686 goto unlock;
4687 }
4688
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004689 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004690 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004691 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4692 hdev);
4693 new_settings(hdev, sk);
4694 goto unlock;
4695 }
4696
Johan Hedberg33e38b32013-03-15 17:07:05 -05004697 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4698 data, len);
4699 if (!cmd) {
4700 err = -ENOMEM;
4701 goto unlock;
4702 }
4703
4704 hci_req_init(&req, hdev);
4705
Johan Hedberg406d7802013-03-15 17:07:09 -05004706 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004707
4708 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004709 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004710 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4711 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004712 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004713 }
4714
Johan Hedberg33e38b32013-03-15 17:07:05 -05004715unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004716 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004717
Antti Julkuf6422ec2011-06-22 13:11:56 +03004718 return err;
4719}
4720
Marcel Holtmann1904a852015-01-11 13:50:44 -08004721static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004722{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004723 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004724
4725 BT_DBG("status 0x%02x", status);
4726
4727 hci_dev_lock(hdev);
4728
4729 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4730 if (!cmd)
4731 goto unlock;
4732
4733 if (status) {
4734 u8 mgmt_err = mgmt_status(status);
4735
4736 /* We need to restore the flag if related HCI commands
4737 * failed.
4738 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004739 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004740
Johan Hedberga69e8372015-03-06 21:08:53 +02004741 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004742 } else {
4743 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4744 new_settings(hdev, cmd->sk);
4745 }
4746
4747 mgmt_pending_remove(cmd);
4748
4749unlock:
4750 hci_dev_unlock(hdev);
4751}
4752
4753static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4754{
4755 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004756 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004757 struct hci_request req;
4758 int err;
4759
4760 BT_DBG("request for %s", hdev->name);
4761
4762 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004763 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4764 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004765
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004766 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004767 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4768 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004769
4770 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004771 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4772 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004773
4774 hci_dev_lock(hdev);
4775
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004776 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004777 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4778 goto unlock;
4779 }
4780
4781 if (!hdev_is_powered(hdev)) {
4782 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004783 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4784 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4785 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4786 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4787 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004788 }
4789
Marcel Holtmannce05d602015-03-13 02:11:03 -07004790 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004791
4792 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4793 if (err < 0)
4794 goto unlock;
4795
4796 err = new_settings(hdev, sk);
4797 goto unlock;
4798 }
4799
4800 /* Reject disabling when powered on */
4801 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004802 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4803 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004804 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004805 } else {
4806 /* When configuring a dual-mode controller to operate
4807 * with LE only and using a static address, then switching
4808 * BR/EDR back on is not allowed.
4809 *
4810 * Dual-mode controllers shall operate with the public
4811 * address as its identity address for BR/EDR and LE. So
4812 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004813 *
4814 * The same restrictions applies when secure connections
4815 * has been enabled. For BR/EDR this is a controller feature
4816 * while for LE it is a host stack feature. This means that
4817 * switching BR/EDR back on when secure connections has been
4818 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004819 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004820 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004821 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004822 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004823 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4824 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004825 goto unlock;
4826 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004827 }
4828
4829 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004830 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4831 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004832 goto unlock;
4833 }
4834
4835 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4836 if (!cmd) {
4837 err = -ENOMEM;
4838 goto unlock;
4839 }
4840
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004841 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004842 * generates the correct flags.
4843 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004844 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004845
4846 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004847
Johan Hedberg432df052014-08-01 11:13:31 +03004848 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004849 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004850
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004851 /* Since only the advertising data flags will change, there
4852 * is no need to update the scan response data.
4853 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004854 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004855
Johan Hedberg0663ca22013-10-02 13:43:14 +03004856 err = hci_req_run(&req, set_bredr_complete);
4857 if (err < 0)
4858 mgmt_pending_remove(cmd);
4859
4860unlock:
4861 hci_dev_unlock(hdev);
4862 return err;
4863}
4864
Johan Hedberga1443f52015-01-23 15:42:46 +02004865static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4866{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004867 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004868 struct mgmt_mode *cp;
4869
4870 BT_DBG("%s status %u", hdev->name, status);
4871
4872 hci_dev_lock(hdev);
4873
4874 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4875 if (!cmd)
4876 goto unlock;
4877
4878 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004879 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4880 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004881 goto remove;
4882 }
4883
4884 cp = cmd->param;
4885
4886 switch (cp->val) {
4887 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004888 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
4889 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004890 break;
4891 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004892 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004893 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004894 break;
4895 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004896 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
4897 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004898 break;
4899 }
4900
4901 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4902 new_settings(hdev, cmd->sk);
4903
4904remove:
4905 mgmt_pending_remove(cmd);
4906unlock:
4907 hci_dev_unlock(hdev);
4908}
4909
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004910static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4911 void *data, u16 len)
4912{
4913 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004914 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004915 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004916 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004917 int err;
4918
4919 BT_DBG("request for %s", hdev->name);
4920
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004921 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004922 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004923 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4924 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004925
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004926 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004927 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004928 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004929 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4930 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004931
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004932 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004933 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004934 MGMT_STATUS_INVALID_PARAMS);
4935
4936 hci_dev_lock(hdev);
4937
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004938 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004939 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004940 bool changed;
4941
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004942 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004943 changed = !test_and_set_bit(HCI_SC_ENABLED,
4944 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004945 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004946 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004947 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004948 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004949 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004950 changed = hci_dev_test_and_clear_flag(hdev,
4951 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004952 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004953 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004954
4955 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4956 if (err < 0)
4957 goto failed;
4958
4959 if (changed)
4960 err = new_settings(hdev, sk);
4961
4962 goto failed;
4963 }
4964
4965 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004966 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4967 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004968 goto failed;
4969 }
4970
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004971 val = !!cp->val;
4972
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004973 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
4974 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004975 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4976 goto failed;
4977 }
4978
4979 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4980 if (!cmd) {
4981 err = -ENOMEM;
4982 goto failed;
4983 }
4984
Johan Hedberga1443f52015-01-23 15:42:46 +02004985 hci_req_init(&req, hdev);
4986 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4987 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004988 if (err < 0) {
4989 mgmt_pending_remove(cmd);
4990 goto failed;
4991 }
4992
4993failed:
4994 hci_dev_unlock(hdev);
4995 return err;
4996}
4997
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004998static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4999 void *data, u16 len)
5000{
5001 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005002 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005003 int err;
5004
5005 BT_DBG("request for %s", hdev->name);
5006
Johan Hedbergb97109792014-06-24 14:00:28 +03005007 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005008 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5009 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005010
5011 hci_dev_lock(hdev);
5012
5013 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03005014 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
5015 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005016 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005017 changed = hci_dev_test_and_clear_flag(hdev,
5018 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005019
Johan Hedbergb97109792014-06-24 14:00:28 +03005020 if (cp->val == 0x02)
5021 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
5022 &hdev->dev_flags);
5023 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005024 use_changed = hci_dev_test_and_clear_flag(hdev,
5025 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005026
5027 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005028 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005029 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5030 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5031 sizeof(mode), &mode);
5032 }
5033
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005034 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5035 if (err < 0)
5036 goto unlock;
5037
5038 if (changed)
5039 err = new_settings(hdev, sk);
5040
5041unlock:
5042 hci_dev_unlock(hdev);
5043 return err;
5044}
5045
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005046static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5047 u16 len)
5048{
5049 struct mgmt_cp_set_privacy *cp = cp_data;
5050 bool changed;
5051 int err;
5052
5053 BT_DBG("request for %s", hdev->name);
5054
5055 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005056 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5057 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005058
5059 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005060 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5061 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005062
5063 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005064 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5065 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005066
5067 hci_dev_lock(hdev);
5068
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005069 /* If user space supports this command it is also expected to
5070 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5071 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005072 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005073
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005074 if (cp->privacy) {
5075 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5076 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005077 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005078 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005079 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005080 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005081 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005082 }
5083
5084 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5085 if (err < 0)
5086 goto unlock;
5087
5088 if (changed)
5089 err = new_settings(hdev, sk);
5090
5091unlock:
5092 hci_dev_unlock(hdev);
5093 return err;
5094}
5095
Johan Hedberg41edf162014-02-18 10:19:35 +02005096static bool irk_is_valid(struct mgmt_irk_info *irk)
5097{
5098 switch (irk->addr.type) {
5099 case BDADDR_LE_PUBLIC:
5100 return true;
5101
5102 case BDADDR_LE_RANDOM:
5103 /* Two most significant bits shall be set */
5104 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5105 return false;
5106 return true;
5107 }
5108
5109 return false;
5110}
5111
5112static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5113 u16 len)
5114{
5115 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005116 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5117 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005118 u16 irk_count, expected_len;
5119 int i, err;
5120
5121 BT_DBG("request for %s", hdev->name);
5122
5123 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005124 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5125 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005126
5127 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005128 if (irk_count > max_irk_count) {
5129 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005130 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5131 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005132 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005133
5134 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5135 if (expected_len != len) {
5136 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005137 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005138 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5139 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005140 }
5141
5142 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5143
5144 for (i = 0; i < irk_count; i++) {
5145 struct mgmt_irk_info *key = &cp->irks[i];
5146
5147 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005148 return mgmt_cmd_status(sk, hdev->id,
5149 MGMT_OP_LOAD_IRKS,
5150 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005151 }
5152
5153 hci_dev_lock(hdev);
5154
5155 hci_smp_irks_clear(hdev);
5156
5157 for (i = 0; i < irk_count; i++) {
5158 struct mgmt_irk_info *irk = &cp->irks[i];
5159 u8 addr_type;
5160
5161 if (irk->addr.type == BDADDR_LE_PUBLIC)
5162 addr_type = ADDR_LE_DEV_PUBLIC;
5163 else
5164 addr_type = ADDR_LE_DEV_RANDOM;
5165
5166 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5167 BDADDR_ANY);
5168 }
5169
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005170 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005171
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005172 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005173
5174 hci_dev_unlock(hdev);
5175
5176 return err;
5177}
5178
Johan Hedberg3f706b72013-01-20 14:27:16 +02005179static bool ltk_is_valid(struct mgmt_ltk_info *key)
5180{
5181 if (key->master != 0x00 && key->master != 0x01)
5182 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005183
5184 switch (key->addr.type) {
5185 case BDADDR_LE_PUBLIC:
5186 return true;
5187
5188 case BDADDR_LE_RANDOM:
5189 /* Two most significant bits shall be set */
5190 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5191 return false;
5192 return true;
5193 }
5194
5195 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005196}
5197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005198static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005199 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005200{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005201 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005202 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5203 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005204 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005205 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005206
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005207 BT_DBG("request for %s", hdev->name);
5208
5209 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005210 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5211 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005212
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005213 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005214 if (key_count > max_key_count) {
5215 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005216 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5217 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005218 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005219
5220 expected_len = sizeof(*cp) + key_count *
5221 sizeof(struct mgmt_ltk_info);
5222 if (expected_len != len) {
5223 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005224 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005225 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5226 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005227 }
5228
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005229 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005230
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005231 for (i = 0; i < key_count; i++) {
5232 struct mgmt_ltk_info *key = &cp->keys[i];
5233
Johan Hedberg3f706b72013-01-20 14:27:16 +02005234 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005235 return mgmt_cmd_status(sk, hdev->id,
5236 MGMT_OP_LOAD_LONG_TERM_KEYS,
5237 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005238 }
5239
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005240 hci_dev_lock(hdev);
5241
5242 hci_smp_ltks_clear(hdev);
5243
5244 for (i = 0; i < key_count; i++) {
5245 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005246 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005247
5248 if (key->addr.type == BDADDR_LE_PUBLIC)
5249 addr_type = ADDR_LE_DEV_PUBLIC;
5250 else
5251 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005252
Johan Hedberg61b43352014-05-29 19:36:53 +03005253 switch (key->type) {
5254 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005255 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005256 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005257 break;
5258 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005259 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005260 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005261 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005262 case MGMT_LTK_P256_UNAUTH:
5263 authenticated = 0x00;
5264 type = SMP_LTK_P256;
5265 break;
5266 case MGMT_LTK_P256_AUTH:
5267 authenticated = 0x01;
5268 type = SMP_LTK_P256;
5269 break;
5270 case MGMT_LTK_P256_DEBUG:
5271 authenticated = 0x00;
5272 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005273 default:
5274 continue;
5275 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005276
Johan Hedberg35d70272014-02-19 14:57:47 +02005277 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005278 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005279 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005280 }
5281
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005282 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005283 NULL, 0);
5284
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005285 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005286
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005287 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005288}
5289
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005290static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005291{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005292 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005293 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005294 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005295
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005296 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005297
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005298 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005299 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005300 rp.tx_power = conn->tx_power;
5301 rp.max_tx_power = conn->max_tx_power;
5302 } else {
5303 rp.rssi = HCI_RSSI_INVALID;
5304 rp.tx_power = HCI_TX_POWER_INVALID;
5305 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005306 }
5307
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005308 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5309 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005310
5311 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005312 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005313
5314 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005315}
5316
Marcel Holtmann1904a852015-01-11 13:50:44 -08005317static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5318 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005319{
5320 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005321 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005322 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005323 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005324 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005325
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005326 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005327
5328 hci_dev_lock(hdev);
5329
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005330 /* Commands sent in request are either Read RSSI or Read Transmit Power
5331 * Level so we check which one was last sent to retrieve connection
5332 * handle. Both commands have handle as first parameter so it's safe to
5333 * cast data on the same command struct.
5334 *
5335 * First command sent is always Read RSSI and we fail only if it fails.
5336 * In other case we simply override error to indicate success as we
5337 * already remembered if TX power value is actually valid.
5338 */
5339 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5340 if (!cp) {
5341 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005342 status = MGMT_STATUS_SUCCESS;
5343 } else {
5344 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005345 }
5346
5347 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005348 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005349 goto unlock;
5350 }
5351
5352 handle = __le16_to_cpu(cp->handle);
5353 conn = hci_conn_hash_lookup_handle(hdev, handle);
5354 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005355 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005356 goto unlock;
5357 }
5358
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005359 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5360 if (!cmd)
5361 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005362
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005363 cmd->cmd_complete(cmd, status);
5364 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005365
5366unlock:
5367 hci_dev_unlock(hdev);
5368}
5369
5370static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5371 u16 len)
5372{
5373 struct mgmt_cp_get_conn_info *cp = data;
5374 struct mgmt_rp_get_conn_info rp;
5375 struct hci_conn *conn;
5376 unsigned long conn_info_age;
5377 int err = 0;
5378
5379 BT_DBG("%s", hdev->name);
5380
5381 memset(&rp, 0, sizeof(rp));
5382 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5383 rp.addr.type = cp->addr.type;
5384
5385 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005386 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5387 MGMT_STATUS_INVALID_PARAMS,
5388 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005389
5390 hci_dev_lock(hdev);
5391
5392 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005393 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5394 MGMT_STATUS_NOT_POWERED, &rp,
5395 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005396 goto unlock;
5397 }
5398
5399 if (cp->addr.type == BDADDR_BREDR)
5400 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5401 &cp->addr.bdaddr);
5402 else
5403 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5404
5405 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005406 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5407 MGMT_STATUS_NOT_CONNECTED, &rp,
5408 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005409 goto unlock;
5410 }
5411
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005412 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005413 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5414 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005415 goto unlock;
5416 }
5417
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005418 /* To avoid client trying to guess when to poll again for information we
5419 * calculate conn info age as random value between min/max set in hdev.
5420 */
5421 conn_info_age = hdev->conn_info_min_age +
5422 prandom_u32_max(hdev->conn_info_max_age -
5423 hdev->conn_info_min_age);
5424
5425 /* Query controller to refresh cached values if they are too old or were
5426 * never read.
5427 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005428 if (time_after(jiffies, conn->conn_info_timestamp +
5429 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005430 !conn->conn_info_timestamp) {
5431 struct hci_request req;
5432 struct hci_cp_read_tx_power req_txp_cp;
5433 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005434 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005435
5436 hci_req_init(&req, hdev);
5437 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5438 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5439 &req_rssi_cp);
5440
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005441 /* For LE links TX power does not change thus we don't need to
5442 * query for it once value is known.
5443 */
5444 if (!bdaddr_type_is_le(cp->addr.type) ||
5445 conn->tx_power == HCI_TX_POWER_INVALID) {
5446 req_txp_cp.handle = cpu_to_le16(conn->handle);
5447 req_txp_cp.type = 0x00;
5448 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5449 sizeof(req_txp_cp), &req_txp_cp);
5450 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005451
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005452 /* Max TX power needs to be read only once per connection */
5453 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5454 req_txp_cp.handle = cpu_to_le16(conn->handle);
5455 req_txp_cp.type = 0x01;
5456 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5457 sizeof(req_txp_cp), &req_txp_cp);
5458 }
5459
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005460 err = hci_req_run(&req, conn_info_refresh_complete);
5461 if (err < 0)
5462 goto unlock;
5463
5464 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5465 data, len);
5466 if (!cmd) {
5467 err = -ENOMEM;
5468 goto unlock;
5469 }
5470
5471 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005472 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005473 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005474
5475 conn->conn_info_timestamp = jiffies;
5476 } else {
5477 /* Cache is valid, just reply with values cached in hci_conn */
5478 rp.rssi = conn->rssi;
5479 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005480 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005481
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005482 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5483 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005484 }
5485
5486unlock:
5487 hci_dev_unlock(hdev);
5488 return err;
5489}
5490
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005491static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005492{
5493 struct hci_conn *conn = cmd->user_data;
5494 struct mgmt_rp_get_clock_info rp;
5495 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005496 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005497
5498 memset(&rp, 0, sizeof(rp));
5499 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5500
5501 if (status)
5502 goto complete;
5503
5504 hdev = hci_dev_get(cmd->index);
5505 if (hdev) {
5506 rp.local_clock = cpu_to_le32(hdev->clock);
5507 hci_dev_put(hdev);
5508 }
5509
5510 if (conn) {
5511 rp.piconet_clock = cpu_to_le32(conn->clock);
5512 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5513 }
5514
5515complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005516 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5517 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005518
5519 if (conn) {
5520 hci_conn_drop(conn);
5521 hci_conn_put(conn);
5522 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005523
5524 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005525}
5526
Marcel Holtmann1904a852015-01-11 13:50:44 -08005527static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005528{
Johan Hedberg95868422014-06-28 17:54:07 +03005529 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005530 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005531 struct hci_conn *conn;
5532
5533 BT_DBG("%s status %u", hdev->name, status);
5534
5535 hci_dev_lock(hdev);
5536
5537 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5538 if (!hci_cp)
5539 goto unlock;
5540
5541 if (hci_cp->which) {
5542 u16 handle = __le16_to_cpu(hci_cp->handle);
5543 conn = hci_conn_hash_lookup_handle(hdev, handle);
5544 } else {
5545 conn = NULL;
5546 }
5547
5548 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5549 if (!cmd)
5550 goto unlock;
5551
Johan Hedberg69487372014-12-05 13:36:07 +02005552 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005553 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005554
5555unlock:
5556 hci_dev_unlock(hdev);
5557}
5558
5559static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5560 u16 len)
5561{
5562 struct mgmt_cp_get_clock_info *cp = data;
5563 struct mgmt_rp_get_clock_info rp;
5564 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005565 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005566 struct hci_request req;
5567 struct hci_conn *conn;
5568 int err;
5569
5570 BT_DBG("%s", hdev->name);
5571
5572 memset(&rp, 0, sizeof(rp));
5573 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5574 rp.addr.type = cp->addr.type;
5575
5576 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005577 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5578 MGMT_STATUS_INVALID_PARAMS,
5579 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005580
5581 hci_dev_lock(hdev);
5582
5583 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005584 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5585 MGMT_STATUS_NOT_POWERED, &rp,
5586 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005587 goto unlock;
5588 }
5589
5590 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5591 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5592 &cp->addr.bdaddr);
5593 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005594 err = mgmt_cmd_complete(sk, hdev->id,
5595 MGMT_OP_GET_CLOCK_INFO,
5596 MGMT_STATUS_NOT_CONNECTED,
5597 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005598 goto unlock;
5599 }
5600 } else {
5601 conn = NULL;
5602 }
5603
5604 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5605 if (!cmd) {
5606 err = -ENOMEM;
5607 goto unlock;
5608 }
5609
Johan Hedberg69487372014-12-05 13:36:07 +02005610 cmd->cmd_complete = clock_info_cmd_complete;
5611
Johan Hedberg95868422014-06-28 17:54:07 +03005612 hci_req_init(&req, hdev);
5613
5614 memset(&hci_cp, 0, sizeof(hci_cp));
5615 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5616
5617 if (conn) {
5618 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005619 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005620
5621 hci_cp.handle = cpu_to_le16(conn->handle);
5622 hci_cp.which = 0x01; /* Piconet clock */
5623 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5624 }
5625
5626 err = hci_req_run(&req, get_clock_info_complete);
5627 if (err < 0)
5628 mgmt_pending_remove(cmd);
5629
5630unlock:
5631 hci_dev_unlock(hdev);
5632 return err;
5633}
5634
Johan Hedberg5a154e62014-12-19 22:26:02 +02005635static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5636{
5637 struct hci_conn *conn;
5638
5639 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5640 if (!conn)
5641 return false;
5642
5643 if (conn->dst_type != type)
5644 return false;
5645
5646 if (conn->state != BT_CONNECTED)
5647 return false;
5648
5649 return true;
5650}
5651
5652/* This function requires the caller holds hdev->lock */
5653static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5654 u8 addr_type, u8 auto_connect)
5655{
5656 struct hci_dev *hdev = req->hdev;
5657 struct hci_conn_params *params;
5658
5659 params = hci_conn_params_add(hdev, addr, addr_type);
5660 if (!params)
5661 return -EIO;
5662
5663 if (params->auto_connect == auto_connect)
5664 return 0;
5665
5666 list_del_init(&params->action);
5667
5668 switch (auto_connect) {
5669 case HCI_AUTO_CONN_DISABLED:
5670 case HCI_AUTO_CONN_LINK_LOSS:
5671 __hci_update_background_scan(req);
5672 break;
5673 case HCI_AUTO_CONN_REPORT:
5674 list_add(&params->action, &hdev->pend_le_reports);
5675 __hci_update_background_scan(req);
5676 break;
5677 case HCI_AUTO_CONN_DIRECT:
5678 case HCI_AUTO_CONN_ALWAYS:
5679 if (!is_connected(hdev, addr, addr_type)) {
5680 list_add(&params->action, &hdev->pend_le_conns);
5681 __hci_update_background_scan(req);
5682 }
5683 break;
5684 }
5685
5686 params->auto_connect = auto_connect;
5687
5688 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5689 auto_connect);
5690
5691 return 0;
5692}
5693
Marcel Holtmann8afef092014-06-29 22:28:34 +02005694static void device_added(struct sock *sk, struct hci_dev *hdev,
5695 bdaddr_t *bdaddr, u8 type, u8 action)
5696{
5697 struct mgmt_ev_device_added ev;
5698
5699 bacpy(&ev.addr.bdaddr, bdaddr);
5700 ev.addr.type = type;
5701 ev.action = action;
5702
5703 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5704}
5705
Marcel Holtmann1904a852015-01-11 13:50:44 -08005706static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005707{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005708 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005709
5710 BT_DBG("status 0x%02x", status);
5711
5712 hci_dev_lock(hdev);
5713
5714 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5715 if (!cmd)
5716 goto unlock;
5717
5718 cmd->cmd_complete(cmd, mgmt_status(status));
5719 mgmt_pending_remove(cmd);
5720
5721unlock:
5722 hci_dev_unlock(hdev);
5723}
5724
Marcel Holtmann2faade52014-06-29 19:44:03 +02005725static int add_device(struct sock *sk, struct hci_dev *hdev,
5726 void *data, u16 len)
5727{
5728 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005729 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005730 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005731 u8 auto_conn, addr_type;
5732 int err;
5733
5734 BT_DBG("%s", hdev->name);
5735
Johan Hedberg66593582014-07-09 12:59:14 +03005736 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005737 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005738 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5739 MGMT_STATUS_INVALID_PARAMS,
5740 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005741
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005742 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
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
Johan Hedberg5a154e62014-12-19 22:26:02 +02005747 hci_req_init(&req, hdev);
5748
Marcel Holtmann2faade52014-06-29 19:44:03 +02005749 hci_dev_lock(hdev);
5750
Johan Hedberg5a154e62014-12-19 22:26:02 +02005751 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5752 if (!cmd) {
5753 err = -ENOMEM;
5754 goto unlock;
5755 }
5756
5757 cmd->cmd_complete = addr_cmd_complete;
5758
Johan Hedberg66593582014-07-09 12:59:14 +03005759 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005760 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005761 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005762 err = cmd->cmd_complete(cmd,
5763 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005764 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005765 goto unlock;
5766 }
5767
5768 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5769 cp->addr.type);
5770 if (err)
5771 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005772
Johan Hedberg5a154e62014-12-19 22:26:02 +02005773 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005774
Johan Hedberg66593582014-07-09 12:59:14 +03005775 goto added;
5776 }
5777
Marcel Holtmann2faade52014-06-29 19:44:03 +02005778 if (cp->addr.type == BDADDR_LE_PUBLIC)
5779 addr_type = ADDR_LE_DEV_PUBLIC;
5780 else
5781 addr_type = ADDR_LE_DEV_RANDOM;
5782
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005783 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005784 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005785 else if (cp->action == 0x01)
5786 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005787 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005788 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005789
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005790 /* If the connection parameters don't exist for this device,
5791 * they will be created and configured with defaults.
5792 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005793 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005794 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005795 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005796 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005797 goto unlock;
5798 }
5799
Johan Hedberg66593582014-07-09 12:59:14 +03005800added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005801 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5802
Johan Hedberg5a154e62014-12-19 22:26:02 +02005803 err = hci_req_run(&req, add_device_complete);
5804 if (err < 0) {
5805 /* ENODATA means no HCI commands were needed (e.g. if
5806 * the adapter is powered off).
5807 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005808 if (err == -ENODATA)
5809 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005810 mgmt_pending_remove(cmd);
5811 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005812
5813unlock:
5814 hci_dev_unlock(hdev);
5815 return err;
5816}
5817
Marcel Holtmann8afef092014-06-29 22:28:34 +02005818static void device_removed(struct sock *sk, struct hci_dev *hdev,
5819 bdaddr_t *bdaddr, u8 type)
5820{
5821 struct mgmt_ev_device_removed ev;
5822
5823 bacpy(&ev.addr.bdaddr, bdaddr);
5824 ev.addr.type = type;
5825
5826 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5827}
5828
Marcel Holtmann1904a852015-01-11 13:50:44 -08005829static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005830{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005831 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005832
5833 BT_DBG("status 0x%02x", status);
5834
5835 hci_dev_lock(hdev);
5836
5837 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5838 if (!cmd)
5839 goto unlock;
5840
5841 cmd->cmd_complete(cmd, mgmt_status(status));
5842 mgmt_pending_remove(cmd);
5843
5844unlock:
5845 hci_dev_unlock(hdev);
5846}
5847
Marcel Holtmann2faade52014-06-29 19:44:03 +02005848static int remove_device(struct sock *sk, struct hci_dev *hdev,
5849 void *data, u16 len)
5850{
5851 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005852 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005853 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005854 int err;
5855
5856 BT_DBG("%s", hdev->name);
5857
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005858 hci_req_init(&req, hdev);
5859
Marcel Holtmann2faade52014-06-29 19:44:03 +02005860 hci_dev_lock(hdev);
5861
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005862 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5863 if (!cmd) {
5864 err = -ENOMEM;
5865 goto unlock;
5866 }
5867
5868 cmd->cmd_complete = addr_cmd_complete;
5869
Marcel Holtmann2faade52014-06-29 19:44:03 +02005870 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005871 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005872 u8 addr_type;
5873
Johan Hedberg66593582014-07-09 12:59:14 +03005874 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005875 err = cmd->cmd_complete(cmd,
5876 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005877 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005878 goto unlock;
5879 }
5880
Johan Hedberg66593582014-07-09 12:59:14 +03005881 if (cp->addr.type == BDADDR_BREDR) {
5882 err = hci_bdaddr_list_del(&hdev->whitelist,
5883 &cp->addr.bdaddr,
5884 cp->addr.type);
5885 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005886 err = cmd->cmd_complete(cmd,
5887 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005888 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005889 goto unlock;
5890 }
5891
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005892 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005893
Johan Hedberg66593582014-07-09 12:59:14 +03005894 device_removed(sk, hdev, &cp->addr.bdaddr,
5895 cp->addr.type);
5896 goto complete;
5897 }
5898
Marcel Holtmann2faade52014-06-29 19:44:03 +02005899 if (cp->addr.type == BDADDR_LE_PUBLIC)
5900 addr_type = ADDR_LE_DEV_PUBLIC;
5901 else
5902 addr_type = ADDR_LE_DEV_RANDOM;
5903
Johan Hedbergc71593d2014-07-02 17:37:28 +03005904 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5905 addr_type);
5906 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005907 err = cmd->cmd_complete(cmd,
5908 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005909 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005910 goto unlock;
5911 }
5912
5913 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005914 err = cmd->cmd_complete(cmd,
5915 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005916 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005917 goto unlock;
5918 }
5919
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005920 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005921 list_del(&params->list);
5922 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005923 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005924
5925 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005926 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005927 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005928 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005929
Marcel Holtmann2faade52014-06-29 19:44:03 +02005930 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005931 err = cmd->cmd_complete(cmd,
5932 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005933 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005934 goto unlock;
5935 }
5936
Johan Hedberg66593582014-07-09 12:59:14 +03005937 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5938 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5939 list_del(&b->list);
5940 kfree(b);
5941 }
5942
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005943 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005944
Johan Hedberg19de0822014-07-06 13:06:51 +03005945 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5946 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5947 continue;
5948 device_removed(sk, hdev, &p->addr, p->addr_type);
5949 list_del(&p->action);
5950 list_del(&p->list);
5951 kfree(p);
5952 }
5953
5954 BT_DBG("All LE connection parameters were removed");
5955
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005956 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005957 }
5958
Johan Hedberg66593582014-07-09 12:59:14 +03005959complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005960 err = hci_req_run(&req, remove_device_complete);
5961 if (err < 0) {
5962 /* ENODATA means no HCI commands were needed (e.g. if
5963 * the adapter is powered off).
5964 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005965 if (err == -ENODATA)
5966 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005967 mgmt_pending_remove(cmd);
5968 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005969
5970unlock:
5971 hci_dev_unlock(hdev);
5972 return err;
5973}
5974
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005975static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5976 u16 len)
5977{
5978 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005979 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5980 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005981 u16 param_count, expected_len;
5982 int i;
5983
5984 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005985 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5986 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005987
5988 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005989 if (param_count > max_param_count) {
5990 BT_ERR("load_conn_param: too big param_count value %u",
5991 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005992 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5993 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005994 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005995
5996 expected_len = sizeof(*cp) + param_count *
5997 sizeof(struct mgmt_conn_param);
5998 if (expected_len != len) {
5999 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6000 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006001 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6002 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006003 }
6004
6005 BT_DBG("%s param_count %u", hdev->name, param_count);
6006
6007 hci_dev_lock(hdev);
6008
6009 hci_conn_params_clear_disabled(hdev);
6010
6011 for (i = 0; i < param_count; i++) {
6012 struct mgmt_conn_param *param = &cp->params[i];
6013 struct hci_conn_params *hci_param;
6014 u16 min, max, latency, timeout;
6015 u8 addr_type;
6016
6017 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6018 param->addr.type);
6019
6020 if (param->addr.type == BDADDR_LE_PUBLIC) {
6021 addr_type = ADDR_LE_DEV_PUBLIC;
6022 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6023 addr_type = ADDR_LE_DEV_RANDOM;
6024 } else {
6025 BT_ERR("Ignoring invalid connection parameters");
6026 continue;
6027 }
6028
6029 min = le16_to_cpu(param->min_interval);
6030 max = le16_to_cpu(param->max_interval);
6031 latency = le16_to_cpu(param->latency);
6032 timeout = le16_to_cpu(param->timeout);
6033
6034 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6035 min, max, latency, timeout);
6036
6037 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6038 BT_ERR("Ignoring invalid connection parameters");
6039 continue;
6040 }
6041
6042 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6043 addr_type);
6044 if (!hci_param) {
6045 BT_ERR("Failed to add connection parameters");
6046 continue;
6047 }
6048
6049 hci_param->conn_min_interval = min;
6050 hci_param->conn_max_interval = max;
6051 hci_param->conn_latency = latency;
6052 hci_param->supervision_timeout = timeout;
6053 }
6054
6055 hci_dev_unlock(hdev);
6056
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006057 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6058 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006059}
6060
Marcel Holtmanndbece372014-07-04 18:11:55 +02006061static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6062 void *data, u16 len)
6063{
6064 struct mgmt_cp_set_external_config *cp = data;
6065 bool changed;
6066 int err;
6067
6068 BT_DBG("%s", hdev->name);
6069
6070 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006071 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6072 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006073
6074 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006075 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6076 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006077
6078 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006079 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6080 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006081
6082 hci_dev_lock(hdev);
6083
6084 if (cp->config)
6085 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6086 &hdev->dev_flags);
6087 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006088 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006089
6090 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6091 if (err < 0)
6092 goto unlock;
6093
6094 if (!changed)
6095 goto unlock;
6096
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006097 err = new_options(hdev, sk);
6098
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006099 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006100 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006101
Marcel Holtmann516018a2015-03-13 02:11:04 -07006102 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006103 hci_dev_set_flag(hdev, HCI_CONFIG);
6104 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006105
6106 queue_work(hdev->req_workqueue, &hdev->power_on);
6107 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006108 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006109 mgmt_index_added(hdev);
6110 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006111 }
6112
6113unlock:
6114 hci_dev_unlock(hdev);
6115 return err;
6116}
6117
Marcel Holtmann9713c172014-07-06 12:11:15 +02006118static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6119 void *data, u16 len)
6120{
6121 struct mgmt_cp_set_public_address *cp = data;
6122 bool changed;
6123 int err;
6124
6125 BT_DBG("%s", hdev->name);
6126
6127 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006128 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6129 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006130
6131 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006132 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6133 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006134
6135 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006136 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6137 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006138
6139 hci_dev_lock(hdev);
6140
6141 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6142 bacpy(&hdev->public_addr, &cp->bdaddr);
6143
6144 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6145 if (err < 0)
6146 goto unlock;
6147
6148 if (!changed)
6149 goto unlock;
6150
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006151 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006152 err = new_options(hdev, sk);
6153
6154 if (is_configured(hdev)) {
6155 mgmt_index_removed(hdev);
6156
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006157 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006158
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006159 hci_dev_set_flag(hdev, HCI_CONFIG);
6160 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006161
6162 queue_work(hdev->req_workqueue, &hdev->power_on);
6163 }
6164
6165unlock:
6166 hci_dev_unlock(hdev);
6167 return err;
6168}
6169
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006170static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006171 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006172 { read_version, MGMT_READ_VERSION_SIZE,
6173 HCI_MGMT_NO_HDEV },
6174 { read_commands, MGMT_READ_COMMANDS_SIZE,
6175 HCI_MGMT_NO_HDEV },
6176 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6177 HCI_MGMT_NO_HDEV },
6178 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6179 { set_powered, MGMT_SETTING_SIZE, 0 },
6180 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6181 { set_connectable, MGMT_SETTING_SIZE, 0 },
6182 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6183 { set_bondable, MGMT_SETTING_SIZE, 0 },
6184 { set_link_security, MGMT_SETTING_SIZE, 0 },
6185 { set_ssp, MGMT_SETTING_SIZE, 0 },
6186 { set_hs, MGMT_SETTING_SIZE, 0 },
6187 { set_le, MGMT_SETTING_SIZE, 0 },
6188 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6189 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6190 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6191 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6192 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6193 HCI_MGMT_VAR_LEN },
6194 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6195 HCI_MGMT_VAR_LEN },
6196 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6197 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6198 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6199 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6200 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6201 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6202 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6203 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6204 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6205 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6206 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6207 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6208 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6209 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6210 HCI_MGMT_VAR_LEN },
6211 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6212 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6213 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6214 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6215 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6216 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6217 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6218 { set_advertising, MGMT_SETTING_SIZE, 0 },
6219 { set_bredr, MGMT_SETTING_SIZE, 0 },
6220 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6221 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6222 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6223 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6224 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6225 { load_irks, MGMT_LOAD_IRKS_SIZE,
6226 HCI_MGMT_VAR_LEN },
6227 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6228 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6229 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6230 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6231 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6232 HCI_MGMT_VAR_LEN },
6233 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6234 HCI_MGMT_NO_HDEV },
6235 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6236 HCI_MGMT_UNCONFIGURED },
6237 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6238 HCI_MGMT_UNCONFIGURED },
6239 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6240 HCI_MGMT_UNCONFIGURED },
6241 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6242 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006243};
6244
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006245int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6246 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006247{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006248 void *buf;
6249 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006250 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006251 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006252 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006253 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006254 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006255 int err;
6256
6257 BT_DBG("got %zu bytes", msglen);
6258
6259 if (msglen < sizeof(*hdr))
6260 return -EINVAL;
6261
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006262 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006263 if (!buf)
6264 return -ENOMEM;
6265
Al Viro6ce8e9c2014-04-06 21:25:44 -04006266 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006267 err = -EFAULT;
6268 goto done;
6269 }
6270
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006271 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006272 opcode = __le16_to_cpu(hdr->opcode);
6273 index = __le16_to_cpu(hdr->index);
6274 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006275
6276 if (len != msglen - sizeof(*hdr)) {
6277 err = -EINVAL;
6278 goto done;
6279 }
6280
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006281 if (opcode >= chan->handler_count ||
6282 chan->handlers[opcode].func == NULL) {
6283 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006284 err = mgmt_cmd_status(sk, index, opcode,
6285 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006286 goto done;
6287 }
6288
6289 handler = &chan->handlers[opcode];
6290
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006291 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006292 hdev = hci_dev_get(index);
6293 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006294 err = mgmt_cmd_status(sk, index, opcode,
6295 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006296 goto done;
6297 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006298
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006299 if (hci_dev_test_flag(hdev, HCI_SETUP) ||
6300 hci_dev_test_flag(hdev, HCI_CONFIG) ||
6301 hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006302 err = mgmt_cmd_status(sk, index, opcode,
6303 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006304 goto done;
6305 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006306
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006307 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006308 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006309 err = mgmt_cmd_status(sk, index, opcode,
6310 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006311 goto done;
6312 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006313 }
6314
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006315 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6316 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006317 err = mgmt_cmd_status(sk, index, opcode,
6318 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006319 goto done;
6320 }
6321
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006322 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6323 if ((var_len && len < handler->data_len) ||
6324 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006325 err = mgmt_cmd_status(sk, index, opcode,
6326 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006327 goto done;
6328 }
6329
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006330 if (hdev)
6331 mgmt_init_hdev(sk, hdev);
6332
6333 cp = buf + sizeof(*hdr);
6334
Johan Hedbergbe22b542012-03-01 22:24:41 +02006335 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006336 if (err < 0)
6337 goto done;
6338
Johan Hedberg03811012010-12-08 00:21:06 +02006339 err = msglen;
6340
6341done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006342 if (hdev)
6343 hci_dev_put(hdev);
6344
Johan Hedberg03811012010-12-08 00:21:06 +02006345 kfree(buf);
6346 return err;
6347}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006348
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006349void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006350{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006351 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006352 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006353
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006354 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6355 return;
6356
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006357 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006358 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6359 else
6360 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006361}
6362
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006363void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006364{
Johan Hedberg5f159032012-03-02 03:13:19 +02006365 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006366
Marcel Holtmann1514b892013-10-06 08:25:01 -07006367 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006368 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006369
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006370 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6371 return;
6372
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006373 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006374
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006375 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmannedd38962014-07-02 21:30:55 +02006376 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6377 else
6378 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006379}
6380
Andre Guedes6046dc32014-02-26 20:21:51 -03006381/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006382static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006383{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006384 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006385 struct hci_conn_params *p;
6386
6387 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006388 /* Needed for AUTO_OFF case where might not "really"
6389 * have been powered off.
6390 */
6391 list_del_init(&p->action);
6392
6393 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006394 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006395 case HCI_AUTO_CONN_ALWAYS:
6396 list_add(&p->action, &hdev->pend_le_conns);
6397 break;
6398 case HCI_AUTO_CONN_REPORT:
6399 list_add(&p->action, &hdev->pend_le_reports);
6400 break;
6401 default:
6402 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006403 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006404 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006405
Johan Hedberg2cf22212014-12-19 22:26:00 +02006406 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006407}
6408
Marcel Holtmann1904a852015-01-11 13:50:44 -08006409static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006410{
6411 struct cmd_lookup match = { NULL, hdev };
6412
6413 BT_DBG("status 0x%02x", status);
6414
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006415 if (!status) {
6416 /* Register the available SMP channels (BR/EDR and LE) only
6417 * when successfully powering on the controller. This late
6418 * registration is required so that LE SMP can clearly
6419 * decide if the public address or static address is used.
6420 */
6421 smp_register(hdev);
6422 }
6423
Johan Hedberg229ab392013-03-15 17:06:53 -05006424 hci_dev_lock(hdev);
6425
6426 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6427
6428 new_settings(hdev, match.sk);
6429
6430 hci_dev_unlock(hdev);
6431
6432 if (match.sk)
6433 sock_put(match.sk);
6434}
6435
Johan Hedberg70da6242013-03-15 17:06:51 -05006436static int powered_update_hci(struct hci_dev *hdev)
6437{
Johan Hedberg890ea892013-03-15 17:06:52 -05006438 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006439 u8 link_sec;
6440
Johan Hedberg890ea892013-03-15 17:06:52 -05006441 hci_req_init(&req, hdev);
6442
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006443 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05006444 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006445 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006446
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006447 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006448
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006449 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6450 u8 support = 0x01;
6451
6452 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6453 sizeof(support), &support);
6454 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006455 }
6456
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006457 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03006458 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006459 struct hci_cp_write_le_host_supported cp;
6460
Marcel Holtmann32226e42014-07-24 20:04:16 +02006461 cp.le = 0x01;
6462 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006463
6464 /* Check first if we already have the right
6465 * host state (host features set)
6466 */
6467 if (cp.le != lmp_host_le_capable(hdev) ||
6468 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006469 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6470 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006471 }
6472
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006473 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006474 /* Make sure the controller has a good default for
6475 * advertising data. This also applies to the case
6476 * where BR/EDR was toggled during the AUTO_OFF phase.
6477 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006478 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006479 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006480 update_scan_rsp_data(&req);
6481 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006482
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006483 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006484 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006485
6486 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006487 }
6488
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006489 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05006490 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006491 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6492 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006493
6494 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006495 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006496 write_fast_connectable(&req, true);
6497 else
6498 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006499 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006500 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006501 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006502 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006503 }
6504
Johan Hedberg229ab392013-03-15 17:06:53 -05006505 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006506}
6507
Johan Hedberg744cf192011-11-08 20:40:14 +02006508int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006509{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006510 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006511 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006512 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006513
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006514 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006515 return 0;
6516
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006517 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006518 if (powered_update_hci(hdev) == 0)
6519 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006520
Johan Hedberg229ab392013-03-15 17:06:53 -05006521 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6522 &match);
6523 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006524 }
6525
Johan Hedberg229ab392013-03-15 17:06:53 -05006526 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006527
6528 /* If the power off is because of hdev unregistration let
6529 * use the appropriate INVALID_INDEX status. Otherwise use
6530 * NOT_POWERED. We cover both scenarios here since later in
6531 * mgmt_index_removed() any hci_conn callbacks will have already
6532 * been triggered, potentially causing misleading DISCONNECTED
6533 * status responses.
6534 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006535 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02006536 status = MGMT_STATUS_INVALID_INDEX;
6537 else
6538 status = MGMT_STATUS_NOT_POWERED;
6539
6540 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006541
6542 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6543 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6544 zero_cod, sizeof(zero_cod), NULL);
6545
6546new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006547 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006548
6549 if (match.sk)
6550 sock_put(match.sk);
6551
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006552 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006553}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006554
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006555void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006556{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006557 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006558 u8 status;
6559
6560 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6561 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006562 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006563
6564 if (err == -ERFKILL)
6565 status = MGMT_STATUS_RFKILLED;
6566 else
6567 status = MGMT_STATUS_FAILED;
6568
Johan Hedberga69e8372015-03-06 21:08:53 +02006569 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006570
6571 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006572}
6573
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006574void mgmt_discoverable_timeout(struct hci_dev *hdev)
6575{
6576 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006577
6578 hci_dev_lock(hdev);
6579
6580 /* When discoverable timeout triggers, then just make sure
6581 * the limited discoverable flag is cleared. Even in the case
6582 * of a timeout triggered from general discoverable, it is
6583 * safe to unconditionally clear the flag.
6584 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006585 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
6586 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006587
6588 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006589 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03006590 u8 scan = SCAN_PAGE;
6591 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6592 sizeof(scan), &scan);
6593 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006594 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006595 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006596 hci_req_run(&req, NULL);
6597
6598 hdev->discov_timeout = 0;
6599
Johan Hedberg9a43e252013-10-20 19:00:07 +03006600 new_settings(hdev, NULL);
6601
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006602 hci_dev_unlock(hdev);
6603}
6604
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006605void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6606 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006607{
Johan Hedberg86742e12011-11-07 23:13:38 +02006608 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006609
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006610 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006611
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006612 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006613 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006614 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006615 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006616 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006617 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006618
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006619 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006620}
Johan Hedbergf7520542011-01-20 12:34:39 +02006621
Johan Hedbergd7b25452014-05-23 13:19:53 +03006622static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6623{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006624 switch (ltk->type) {
6625 case SMP_LTK:
6626 case SMP_LTK_SLAVE:
6627 if (ltk->authenticated)
6628 return MGMT_LTK_AUTHENTICATED;
6629 return MGMT_LTK_UNAUTHENTICATED;
6630 case SMP_LTK_P256:
6631 if (ltk->authenticated)
6632 return MGMT_LTK_P256_AUTH;
6633 return MGMT_LTK_P256_UNAUTH;
6634 case SMP_LTK_P256_DEBUG:
6635 return MGMT_LTK_P256_DEBUG;
6636 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006637
6638 return MGMT_LTK_UNAUTHENTICATED;
6639}
6640
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006641void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006642{
6643 struct mgmt_ev_new_long_term_key ev;
6644
6645 memset(&ev, 0, sizeof(ev));
6646
Marcel Holtmann5192d302014-02-19 17:11:58 -08006647 /* Devices using resolvable or non-resolvable random addresses
6648 * without providing an indentity resolving key don't require
6649 * to store long term keys. Their addresses will change the
6650 * next time around.
6651 *
6652 * Only when a remote device provides an identity address
6653 * make sure the long term key is stored. If the remote
6654 * identity is known, the long term keys are internally
6655 * mapped to the identity address. So allow static random
6656 * and public addresses here.
6657 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006658 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6659 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6660 ev.store_hint = 0x00;
6661 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006662 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006663
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006664 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006665 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006666 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006667 ev.key.enc_size = key->enc_size;
6668 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006669 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006670
Johan Hedberg2ceba532014-06-16 19:25:16 +03006671 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006672 ev.key.master = 1;
6673
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006674 memcpy(ev.key.val, key->val, sizeof(key->val));
6675
Marcel Holtmann083368f2013-10-15 14:26:29 -07006676 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006677}
6678
Johan Hedberg95fbac82014-02-19 15:18:31 +02006679void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6680{
6681 struct mgmt_ev_new_irk ev;
6682
6683 memset(&ev, 0, sizeof(ev));
6684
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006685 /* For identity resolving keys from devices that are already
6686 * using a public address or static random address, do not
6687 * ask for storing this key. The identity resolving key really
6688 * is only mandatory for devices using resovlable random
6689 * addresses.
6690 *
6691 * Storing all identity resolving keys has the downside that
6692 * they will be also loaded on next boot of they system. More
6693 * identity resolving keys, means more time during scanning is
6694 * needed to actually resolve these addresses.
6695 */
6696 if (bacmp(&irk->rpa, BDADDR_ANY))
6697 ev.store_hint = 0x01;
6698 else
6699 ev.store_hint = 0x00;
6700
Johan Hedberg95fbac82014-02-19 15:18:31 +02006701 bacpy(&ev.rpa, &irk->rpa);
6702 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6703 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6704 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6705
6706 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6707}
6708
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006709void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6710 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006711{
6712 struct mgmt_ev_new_csrk ev;
6713
6714 memset(&ev, 0, sizeof(ev));
6715
6716 /* Devices using resolvable or non-resolvable random addresses
6717 * without providing an indentity resolving key don't require
6718 * to store signature resolving keys. Their addresses will change
6719 * the next time around.
6720 *
6721 * Only when a remote device provides an identity address
6722 * make sure the signature resolving key is stored. So allow
6723 * static random and public addresses here.
6724 */
6725 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6726 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6727 ev.store_hint = 0x00;
6728 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006729 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006730
6731 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6732 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006733 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006734 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6735
6736 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6737}
6738
Andre Guedesffb5a8272014-07-01 18:10:11 -03006739void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006740 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6741 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006742{
6743 struct mgmt_ev_new_conn_param ev;
6744
Johan Hedbergc103aea2014-07-02 17:37:34 +03006745 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6746 return;
6747
Andre Guedesffb5a8272014-07-01 18:10:11 -03006748 memset(&ev, 0, sizeof(ev));
6749 bacpy(&ev.addr.bdaddr, bdaddr);
6750 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006751 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006752 ev.min_interval = cpu_to_le16(min_interval);
6753 ev.max_interval = cpu_to_le16(max_interval);
6754 ev.latency = cpu_to_le16(latency);
6755 ev.timeout = cpu_to_le16(timeout);
6756
6757 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6758}
6759
Marcel Holtmann94933992013-10-15 10:26:39 -07006760static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6761 u8 data_len)
6762{
6763 eir[eir_len++] = sizeof(type) + data_len;
6764 eir[eir_len++] = type;
6765 memcpy(&eir[eir_len], data, data_len);
6766 eir_len += data_len;
6767
6768 return eir_len;
6769}
6770
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006771void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6772 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006773{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006774 char buf[512];
6775 struct mgmt_ev_device_connected *ev = (void *) buf;
6776 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006777
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006778 bacpy(&ev->addr.bdaddr, &conn->dst);
6779 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006780
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006781 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006782
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006783 /* We must ensure that the EIR Data fields are ordered and
6784 * unique. Keep it simple for now and avoid the problem by not
6785 * adding any BR/EDR data to the LE adv.
6786 */
6787 if (conn->le_adv_data_len > 0) {
6788 memcpy(&ev->eir[eir_len],
6789 conn->le_adv_data, conn->le_adv_data_len);
6790 eir_len = conn->le_adv_data_len;
6791 } else {
6792 if (name_len > 0)
6793 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6794 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006795
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006796 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006797 eir_len = eir_append_data(ev->eir, eir_len,
6798 EIR_CLASS_OF_DEV,
6799 conn->dev_class, 3);
6800 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006801
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006802 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006803
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006804 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6805 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006806}
6807
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006808static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006809{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006810 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006811
Johan Hedbergf5818c22014-12-05 13:36:02 +02006812 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006813
6814 *sk = cmd->sk;
6815 sock_hold(*sk);
6816
Johan Hedberga664b5b2011-02-19 12:06:02 -03006817 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006818}
6819
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006820static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006821{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006822 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006823 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006824
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006825 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6826
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006827 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006828 mgmt_pending_remove(cmd);
6829}
6830
Johan Hedberg84c61d92014-08-01 11:13:30 +03006831bool mgmt_powering_down(struct hci_dev *hdev)
6832{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006833 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006834 struct mgmt_mode *cp;
6835
6836 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6837 if (!cmd)
6838 return false;
6839
6840 cp = cmd->param;
6841 if (!cp->val)
6842 return true;
6843
6844 return false;
6845}
6846
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006847void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006848 u8 link_type, u8 addr_type, u8 reason,
6849 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006850{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006851 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006852 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006853
Johan Hedberg84c61d92014-08-01 11:13:30 +03006854 /* The connection is still in hci_conn_hash so test for 1
6855 * instead of 0 to know if this is the last one.
6856 */
6857 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6858 cancel_delayed_work(&hdev->power_off);
6859 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006860 }
6861
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006862 if (!mgmt_connected)
6863 return;
6864
Andre Guedes57eb7762013-10-30 19:01:41 -03006865 if (link_type != ACL_LINK && link_type != LE_LINK)
6866 return;
6867
Johan Hedberg744cf192011-11-08 20:40:14 +02006868 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006869
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006870 bacpy(&ev.addr.bdaddr, bdaddr);
6871 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6872 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006873
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006874 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006875
6876 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006877 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006878
Johan Hedberg124f6e32012-02-09 13:50:12 +02006879 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006880 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006881}
6882
Marcel Holtmann78929242013-10-06 23:55:47 -07006883void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6884 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006885{
Andre Guedes3655bba2013-10-30 19:01:40 -03006886 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6887 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006888 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006889
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006890 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6891 hdev);
6892
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006893 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006894 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006895 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006896
Andre Guedes3655bba2013-10-30 19:01:40 -03006897 cp = cmd->param;
6898
6899 if (bacmp(bdaddr, &cp->addr.bdaddr))
6900 return;
6901
6902 if (cp->addr.type != bdaddr_type)
6903 return;
6904
Johan Hedbergf5818c22014-12-05 13:36:02 +02006905 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006906 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006907}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006908
Marcel Holtmann445608d2013-10-06 23:55:48 -07006909void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6910 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006911{
6912 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006913
Johan Hedberg84c61d92014-08-01 11:13:30 +03006914 /* The connection is still in hci_conn_hash so test for 1
6915 * instead of 0 to know if this is the last one.
6916 */
6917 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6918 cancel_delayed_work(&hdev->power_off);
6919 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006920 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006921
Johan Hedberg4c659c32011-11-07 23:13:39 +02006922 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006923 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006924 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006925
Marcel Holtmann445608d2013-10-06 23:55:48 -07006926 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006927}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006928
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006929void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006930{
6931 struct mgmt_ev_pin_code_request ev;
6932
Johan Hedbergd8457692012-02-17 14:24:57 +02006933 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006934 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006935 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006936
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006937 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006938}
6939
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006940void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6941 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006942{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006943 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006944
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006945 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006946 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006947 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006948
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006949 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006950 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006951}
6952
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006953void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6954 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006955{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006956 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006957
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006958 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006959 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006960 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006961
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006962 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006963 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006964}
Johan Hedberga5c29682011-02-19 12:05:57 -03006965
Johan Hedberg744cf192011-11-08 20:40:14 +02006966int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006967 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006968 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006969{
6970 struct mgmt_ev_user_confirm_request ev;
6971
Johan Hedberg744cf192011-11-08 20:40:14 +02006972 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006973
Johan Hedberg272d90d2012-02-09 15:26:12 +02006974 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006975 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006976 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006977 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006978
Johan Hedberg744cf192011-11-08 20:40:14 +02006979 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006980 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006981}
6982
Johan Hedberg272d90d2012-02-09 15:26:12 +02006983int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006984 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006985{
6986 struct mgmt_ev_user_passkey_request ev;
6987
6988 BT_DBG("%s", hdev->name);
6989
Johan Hedberg272d90d2012-02-09 15:26:12 +02006990 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006991 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006992
6993 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006994 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006995}
6996
Brian Gix0df4c182011-11-16 13:53:13 -08006997static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006998 u8 link_type, u8 addr_type, u8 status,
6999 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007000{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007001 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007002
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007003 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007004 if (!cmd)
7005 return -ENOENT;
7006
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007007 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007008 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007009
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007010 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007011}
7012
Johan Hedberg744cf192011-11-08 20:40:14 +02007013int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007014 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007015{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007016 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007017 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007018}
7019
Johan Hedberg272d90d2012-02-09 15:26:12 +02007020int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007021 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007022{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007023 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007024 status,
7025 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007026}
Johan Hedberg2a611692011-02-19 12:06:00 -03007027
Brian Gix604086b2011-11-23 08:28:33 -08007028int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007029 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007030{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007031 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007032 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007033}
7034
Johan Hedberg272d90d2012-02-09 15:26:12 +02007035int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007036 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007037{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007038 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007039 status,
7040 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007041}
7042
Johan Hedberg92a25252012-09-06 18:39:26 +03007043int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7044 u8 link_type, u8 addr_type, u32 passkey,
7045 u8 entered)
7046{
7047 struct mgmt_ev_passkey_notify ev;
7048
7049 BT_DBG("%s", hdev->name);
7050
7051 bacpy(&ev.addr.bdaddr, bdaddr);
7052 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7053 ev.passkey = __cpu_to_le32(passkey);
7054 ev.entered = entered;
7055
7056 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7057}
7058
Johan Hedberge1e930f2014-09-08 17:09:49 -07007059void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007060{
7061 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007062 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007063 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007064
Johan Hedberge1e930f2014-09-08 17:09:49 -07007065 bacpy(&ev.addr.bdaddr, &conn->dst);
7066 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7067 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007068
Johan Hedberge1e930f2014-09-08 17:09:49 -07007069 cmd = find_pairing(conn);
7070
7071 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7072 cmd ? cmd->sk : NULL);
7073
Johan Hedberga511b352014-12-11 21:45:45 +02007074 if (cmd) {
7075 cmd->cmd_complete(cmd, status);
7076 mgmt_pending_remove(cmd);
7077 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007078}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007079
Marcel Holtmann464996a2013-10-15 14:26:24 -07007080void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007081{
7082 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007083 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007084
7085 if (status) {
7086 u8 mgmt_err = mgmt_status(status);
7087 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007088 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007089 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007090 }
7091
Marcel Holtmann464996a2013-10-15 14:26:24 -07007092 if (test_bit(HCI_AUTH, &hdev->flags))
7093 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7094 &hdev->dev_flags);
7095 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007096 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007097
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007098 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007099 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007100
Johan Hedberg47990ea2012-02-22 11:58:37 +02007101 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007102 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007103
7104 if (match.sk)
7105 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007106}
7107
Johan Hedberg890ea892013-03-15 17:06:52 -05007108static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007109{
Johan Hedberg890ea892013-03-15 17:06:52 -05007110 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007111 struct hci_cp_write_eir cp;
7112
Johan Hedberg976eb202012-10-24 21:12:01 +03007113 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007114 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007115
Johan Hedbergc80da272012-02-22 15:38:48 +02007116 memset(hdev->eir, 0, sizeof(hdev->eir));
7117
Johan Hedbergcacaf522012-02-21 00:52:42 +02007118 memset(&cp, 0, sizeof(cp));
7119
Johan Hedberg890ea892013-03-15 17:06:52 -05007120 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007121}
7122
Marcel Holtmann3e248562013-10-15 14:26:25 -07007123void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007124{
7125 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007126 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007127 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007128
7129 if (status) {
7130 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007131
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007132 if (enable && hci_dev_test_and_clear_flag(hdev,
7133 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007134 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007135 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007136 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007137
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007138 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7139 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007140 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007141 }
7142
7143 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007144 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007145 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007146 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007147 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007148 changed = hci_dev_test_and_clear_flag(hdev,
7149 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007150 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007151 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007152 }
7153
7154 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7155
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007156 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007157 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007158
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007159 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007160 sock_put(match.sk);
7161
Johan Hedberg890ea892013-03-15 17:06:52 -05007162 hci_req_init(&req, hdev);
7163
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007164 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7165 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007166 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7167 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007168 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007169 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007170 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007171 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007172
7173 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007174}
7175
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007176static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007177{
7178 struct cmd_lookup *match = data;
7179
Johan Hedberg90e70452012-02-23 23:09:40 +02007180 if (match->sk == NULL) {
7181 match->sk = cmd->sk;
7182 sock_hold(match->sk);
7183 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007184}
7185
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007186void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7187 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007188{
Johan Hedberg90e70452012-02-23 23:09:40 +02007189 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007190
Johan Hedberg92da6092013-03-15 17:06:55 -05007191 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7192 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7193 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007194
7195 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007196 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7197 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007198
7199 if (match.sk)
7200 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007201}
7202
Marcel Holtmann7667da32013-10-15 14:26:27 -07007203void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007204{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007205 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007206 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007207
Johan Hedberg13928972013-03-15 17:07:00 -05007208 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007209 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007210
7211 memset(&ev, 0, sizeof(ev));
7212 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007213 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007214
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007215 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007216 if (!cmd) {
7217 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007218
Johan Hedberg13928972013-03-15 17:07:00 -05007219 /* If this is a HCI command related to powering on the
7220 * HCI dev don't send any mgmt signals.
7221 */
7222 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007223 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007224 }
7225
Marcel Holtmann7667da32013-10-15 14:26:27 -07007226 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7227 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007228}
Szymon Jancc35938b2011-03-22 13:12:21 +01007229
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007230void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007231 u8 *rand192, u8 *hash256, u8 *rand256,
7232 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007233{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007234 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007235
Johan Hedberg744cf192011-11-08 20:40:14 +02007236 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007237
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007238 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007239 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007240 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007241
7242 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007243 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7244 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007245 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007246 struct mgmt_rp_read_local_oob_data rp;
7247 size_t rp_size = sizeof(rp);
7248
7249 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7250 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7251
Johan Hedberg710f11c2014-05-26 11:21:22 +03007252 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007253 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007254 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007255 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007256 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007257 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007258
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007259 mgmt_cmd_complete(cmd->sk, hdev->id,
7260 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7261 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007262 }
7263
7264 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007265}
Johan Hedberge17acd42011-03-30 23:57:16 +03007266
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007267static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7268{
7269 int i;
7270
7271 for (i = 0; i < uuid_count; i++) {
7272 if (!memcmp(uuid, uuids[i], 16))
7273 return true;
7274 }
7275
7276 return false;
7277}
7278
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007279static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7280{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007281 u16 parsed = 0;
7282
7283 while (parsed < eir_len) {
7284 u8 field_len = eir[0];
7285 u8 uuid[16];
7286 int i;
7287
7288 if (field_len == 0)
7289 break;
7290
7291 if (eir_len - parsed < field_len + 1)
7292 break;
7293
7294 switch (eir[1]) {
7295 case EIR_UUID16_ALL:
7296 case EIR_UUID16_SOME:
7297 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007298 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007299 uuid[13] = eir[i + 3];
7300 uuid[12] = eir[i + 2];
7301 if (has_uuid(uuid, uuid_count, uuids))
7302 return true;
7303 }
7304 break;
7305 case EIR_UUID32_ALL:
7306 case EIR_UUID32_SOME:
7307 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007308 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007309 uuid[15] = eir[i + 5];
7310 uuid[14] = eir[i + 4];
7311 uuid[13] = eir[i + 3];
7312 uuid[12] = eir[i + 2];
7313 if (has_uuid(uuid, uuid_count, uuids))
7314 return true;
7315 }
7316 break;
7317 case EIR_UUID128_ALL:
7318 case EIR_UUID128_SOME:
7319 for (i = 0; i + 17 <= field_len; i += 16) {
7320 memcpy(uuid, eir + i + 2, 16);
7321 if (has_uuid(uuid, uuid_count, uuids))
7322 return true;
7323 }
7324 break;
7325 }
7326
7327 parsed += field_len + 1;
7328 eir += field_len + 1;
7329 }
7330
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007331 return false;
7332}
7333
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007334static void restart_le_scan(struct hci_dev *hdev)
7335{
7336 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007337 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007338 return;
7339
7340 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7341 hdev->discovery.scan_start +
7342 hdev->discovery.scan_duration))
7343 return;
7344
7345 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7346 DISCOV_LE_RESTART_DELAY);
7347}
7348
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007349static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7350 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7351{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007352 /* If a RSSI threshold has been specified, and
7353 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7354 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7355 * is set, let it through for further processing, as we might need to
7356 * restart the scan.
7357 *
7358 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7359 * the results are also dropped.
7360 */
7361 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7362 (rssi == HCI_RSSI_INVALID ||
7363 (rssi < hdev->discovery.rssi &&
7364 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7365 return false;
7366
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007367 if (hdev->discovery.uuid_count != 0) {
7368 /* If a list of UUIDs is provided in filter, results with no
7369 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007370 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007371 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7372 hdev->discovery.uuids) &&
7373 !eir_has_uuids(scan_rsp, scan_rsp_len,
7374 hdev->discovery.uuid_count,
7375 hdev->discovery.uuids))
7376 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007377 }
7378
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007379 /* If duplicate filtering does not report RSSI changes, then restart
7380 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007381 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007382 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7383 restart_le_scan(hdev);
7384
7385 /* Validate RSSI value against the RSSI threshold once more. */
7386 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7387 rssi < hdev->discovery.rssi)
7388 return false;
7389 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007390
7391 return true;
7392}
7393
Marcel Holtmann901801b2013-10-06 23:55:51 -07007394void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007395 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7396 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007397{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007398 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007399 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007400 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007401
Johan Hedberg75ce2082014-07-02 22:42:01 +03007402 /* Don't send events for a non-kernel initiated discovery. With
7403 * LE one exception is if we have pend_le_reports > 0 in which
7404 * case we're doing passive scanning and want these events.
7405 */
7406 if (!hci_discovery_active(hdev)) {
7407 if (link_type == ACL_LINK)
7408 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007409 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007410 return;
7411 }
Andre Guedes12602d02013-04-30 15:29:40 -03007412
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007413 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007414 /* We are using service discovery */
7415 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7416 scan_rsp_len))
7417 return;
7418 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007419
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007420 /* Make sure that the buffer is big enough. The 5 extra bytes
7421 * are for the potential CoD field.
7422 */
7423 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007424 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007425
Johan Hedberg1dc06092012-01-15 21:01:23 +02007426 memset(buf, 0, sizeof(buf));
7427
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007428 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7429 * RSSI value was reported as 0 when not available. This behavior
7430 * is kept when using device discovery. This is required for full
7431 * backwards compatibility with the API.
7432 *
7433 * However when using service discovery, the value 127 will be
7434 * returned when the RSSI is not available.
7435 */
Szymon Janc91200e92015-01-22 16:57:05 +01007436 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7437 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007438 rssi = 0;
7439
Johan Hedberg841c5642014-07-07 12:45:54 +03007440 bacpy(&ev->addr.bdaddr, bdaddr);
7441 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007442 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007443 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007444
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007445 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007446 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007447 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007448
Johan Hedberg1dc06092012-01-15 21:01:23 +02007449 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7450 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007451 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007452
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007453 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007454 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007455 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007456
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007457 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7458 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007459
Marcel Holtmann901801b2013-10-06 23:55:51 -07007460 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007461}
Johan Hedberga88a9652011-03-30 13:18:12 +03007462
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007463void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7464 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007465{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007466 struct mgmt_ev_device_found *ev;
7467 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7468 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007469
Johan Hedbergb644ba32012-01-17 21:48:47 +02007470 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007471
Johan Hedbergb644ba32012-01-17 21:48:47 +02007472 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007473
Johan Hedbergb644ba32012-01-17 21:48:47 +02007474 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007475 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007476 ev->rssi = rssi;
7477
7478 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007479 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007480
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007481 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007482
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007483 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007484}
Johan Hedberg314b2382011-04-27 10:29:57 -04007485
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007486void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007487{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007488 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007489
Andre Guedes343fb142011-11-22 17:14:19 -03007490 BT_DBG("%s discovering %u", hdev->name, discovering);
7491
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007492 memset(&ev, 0, sizeof(ev));
7493 ev.type = hdev->discovery.type;
7494 ev.discovering = discovering;
7495
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007496 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007497}
Antti Julku5e762442011-08-25 16:48:02 +03007498
Marcel Holtmann1904a852015-01-11 13:50:44 -08007499static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007500{
7501 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007502}
7503
7504void mgmt_reenable_advertising(struct hci_dev *hdev)
7505{
7506 struct hci_request req;
7507
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007508 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmann5976e602013-10-06 04:08:14 -07007509 return;
7510
7511 hci_req_init(&req, hdev);
7512 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007513 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007514}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007515
7516static struct hci_mgmt_chan chan = {
7517 .channel = HCI_CHANNEL_CONTROL,
7518 .handler_count = ARRAY_SIZE(mgmt_handlers),
7519 .handlers = mgmt_handlers,
7520};
7521
7522int mgmt_init(void)
7523{
7524 return hci_mgmt_chan_register(&chan);
7525}
7526
7527void mgmt_exit(void)
7528{
7529 hci_mgmt_chan_unregister(&chan);
7530}