blob: 924bf3ee6261cc4ac883f872f8b6fdaa8f89fee6 [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 Holtmann04c60f02014-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 Holtmann04c60f02014-07-04 19:06:22 +0200248 kfree_skb(skb);
249
250 return 0;
251}
252
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200253static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
254 struct sock *skip_sk)
255{
256 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
257 skip_sk);
258}
259
Johan Hedberga69e8372015-03-06 21:08:53 +0200260static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200261{
262 struct sk_buff *skb;
263 struct mgmt_hdr *hdr;
264 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300265 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200266
Szymon Janc34eb5252011-02-28 14:10:08 +0100267 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200268
Andre Guedes790eff42012-06-07 19:05:46 -0300269 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200270 if (!skb)
271 return -ENOMEM;
272
273 hdr = (void *) skb_put(skb, sizeof(*hdr));
274
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100276 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200277 hdr->len = cpu_to_le16(sizeof(*ev));
278
279 ev = (void *) skb_put(skb, sizeof(*ev));
280 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200281 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200282
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 err = sock_queue_rcv_skb(sk, skb);
284 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200285 kfree_skb(skb);
286
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300287 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200288}
289
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200290static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
291 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200292{
293 struct sk_buff *skb;
294 struct mgmt_hdr *hdr;
295 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300296 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200297
298 BT_DBG("sock %p", sk);
299
Andre Guedes790eff42012-06-07 19:05:46 -0300300 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200301 if (!skb)
302 return -ENOMEM;
303
304 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200305
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700306 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100307 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200308 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200309
Johan Hedberga38528f2011-01-22 06:46:43 +0200310 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200311 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200312 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100313
314 if (rp)
315 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200316
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300317 err = sock_queue_rcv_skb(sk, skb);
318 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200319 kfree_skb(skb);
320
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100321 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200322}
323
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300324static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
325 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200326{
327 struct mgmt_rp_read_version rp;
328
329 BT_DBG("sock %p", sk);
330
331 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700332 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200333
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200334 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
335 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200336}
337
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300338static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
339 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200340{
341 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200342 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
343 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200344 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345 size_t rp_size;
346 int i, err;
347
348 BT_DBG("sock %p", sk);
349
350 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
351
352 rp = kmalloc(rp_size, GFP_KERNEL);
353 if (!rp)
354 return -ENOMEM;
355
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700356 rp->num_commands = cpu_to_le16(num_commands);
357 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200358
359 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
360 put_unaligned_le16(mgmt_commands[i], opcode);
361
362 for (i = 0; i < num_events; i++, opcode++)
363 put_unaligned_le16(mgmt_events[i], opcode);
364
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200365 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
366 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200367 kfree(rp);
368
369 return err;
370}
371
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300372static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
373 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200376 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200377 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200378 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300379 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200380
381 BT_DBG("sock %p", sk);
382
383 read_lock(&hci_dev_list_lock);
384
385 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300386 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200387 if (d->dev_type == HCI_BREDR &&
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 Hedbergf7b64e62010-12-13 21:07:06 +0200596
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200597 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
598 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200599 settings |= MGMT_SETTING_CONFIGURATION;
600
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200601 return settings;
602}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200603
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604static u32 get_current_settings(struct hci_dev *hdev)
605{
606 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200607
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200608 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100609 settings |= MGMT_SETTING_POWERED;
610
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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-12-13 21:07:06 +0200634
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700635 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200636 settings |= MGMT_SETTING_HS;
637
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700638 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300639 settings |= MGMT_SETTING_ADVERTISING;
640
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700641 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800642 settings |= MGMT_SETTING_SECURE_CONN;
643
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700644 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800645 settings |= MGMT_SETTING_DEBUG_KEYS;
646
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700647 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200648 settings |= MGMT_SETTING_PRIVACY;
649
Marcel Holtmann93690c22015-03-06 10:11:21 -0800650 /* The current setting for static address has two purposes. The
651 * first is to indicate if the static address will be used and
652 * the second is to indicate if it is actually set.
653 *
654 * This means if the static address is not configured, this flag
655 * will never bet set. If the address is configured, then if the
656 * address is actually used decides if the flag is set or not.
657 *
658 * For single mode LE only controllers and dual-mode controllers
659 * with BR/EDR disabled, the existence of the static address will
660 * be evaluated.
661 */
662 if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700663 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800664 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
665 if (bacmp(&hdev->static_addr, BDADDR_ANY))
666 settings |= MGMT_SETTING_STATIC_ADDRESS;
667 }
668
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200669 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200670}
671
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300672#define PNP_INFO_SVCLASS_ID 0x1200
673
Johan Hedberg213202e2013-01-27 00:31:33 +0200674static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
675{
676 u8 *ptr = data, *uuids_start = NULL;
677 struct bt_uuid *uuid;
678
679 if (len < 4)
680 return ptr;
681
682 list_for_each_entry(uuid, &hdev->uuids, list) {
683 u16 uuid16;
684
685 if (uuid->size != 16)
686 continue;
687
688 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
689 if (uuid16 < 0x1100)
690 continue;
691
692 if (uuid16 == PNP_INFO_SVCLASS_ID)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID16_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u16) > len) {
704 uuids_start[1] = EIR_UUID16_SOME;
705 break;
706 }
707
708 *ptr++ = (uuid16 & 0x00ff);
709 *ptr++ = (uuid16 & 0xff00) >> 8;
710 uuids_start[0] += sizeof(uuid16);
711 }
712
713 return ptr;
714}
715
Johan Hedbergcdf19632013-01-27 00:31:34 +0200716static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 6)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 32)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID32_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + sizeof(u32) > len) {
737 uuids_start[1] = EIR_UUID32_SOME;
738 break;
739 }
740
741 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
742 ptr += sizeof(u32);
743 uuids_start[0] += sizeof(u32);
744 }
745
746 return ptr;
747}
748
Johan Hedbergc00d5752013-01-27 00:31:35 +0200749static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
750{
751 u8 *ptr = data, *uuids_start = NULL;
752 struct bt_uuid *uuid;
753
754 if (len < 18)
755 return ptr;
756
757 list_for_each_entry(uuid, &hdev->uuids, list) {
758 if (uuid->size != 128)
759 continue;
760
761 if (!uuids_start) {
762 uuids_start = ptr;
763 uuids_start[0] = 1;
764 uuids_start[1] = EIR_UUID128_ALL;
765 ptr += 2;
766 }
767
768 /* Stop if not enough space to put next UUID */
769 if ((ptr - data) + 16 > len) {
770 uuids_start[1] = EIR_UUID128_SOME;
771 break;
772 }
773
774 memcpy(ptr, uuid->uuid, 16);
775 ptr += 16;
776 uuids_start[0] += 16;
777 }
778
779 return ptr;
780}
781
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200782static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
783 struct hci_dev *hdev)
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300784{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200785 struct mgmt_pending_cmd *cmd;
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300786
787 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
788 if (cmd->opcode == opcode)
789 return cmd;
790 }
791
792 return NULL;
793}
794
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200795static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
796 struct hci_dev *hdev,
797 const void *data)
Johan Hedberg95868422014-06-28 17:54:07 +0300798{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200799 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +0300800
801 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
802 if (cmd->user_data != data)
803 continue;
804 if (cmd->opcode == opcode)
805 return cmd;
806 }
807
808 return NULL;
809}
810
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
812{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700813 u8 ad_len = 0;
814 size_t name_len;
815
816 name_len = strlen(hdev->dev_name);
817 if (name_len > 0) {
818 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
819
820 if (name_len > max_len) {
821 name_len = max_len;
822 ptr[1] = EIR_NAME_SHORT;
823 } else
824 ptr[1] = EIR_NAME_COMPLETE;
825
826 ptr[0] = name_len + 1;
827
828 memcpy(ptr + 2, hdev->dev_name, name_len);
829
830 ad_len += (name_len + 2);
831 ptr += (name_len + 2);
832 }
833
834 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700835}
836
837static void update_scan_rsp_data(struct hci_request *req)
838{
839 struct hci_dev *hdev = req->hdev;
840 struct hci_cp_le_set_scan_rsp_data cp;
841 u8 len;
842
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700843 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700844 return;
845
846 memset(&cp, 0, sizeof(cp));
847
848 len = create_scan_rsp_data(hdev, cp.data);
849
Johan Hedbergeb438b52013-10-16 15:31:07 +0300850 if (hdev->scan_rsp_data_len == len &&
851 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700852 return;
853
Johan Hedbergeb438b52013-10-16 15:31:07 +0300854 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
855 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700856
857 cp.length = len;
858
859 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
860}
861
Johan Hedberg9a43e252013-10-20 19:00:07 +0300862static u8 get_adv_discov_flags(struct hci_dev *hdev)
863{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200864 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300865
866 /* If there's a pending mgmt command the flags will not yet have
867 * their final values, so check for this first.
868 */
869 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
870 if (cmd) {
871 struct mgmt_mode *cp = cmd->param;
872 if (cp->val == 0x01)
873 return LE_AD_GENERAL;
874 else if (cp->val == 0x02)
875 return LE_AD_LIMITED;
876 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700877 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300878 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700879 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300880 return LE_AD_GENERAL;
881 }
882
883 return 0;
884}
885
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700886static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700887{
888 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700889
Johan Hedberg9a43e252013-10-20 19:00:07 +0300890 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700892 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700893 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700894
895 if (flags) {
896 BT_DBG("adv flags 0x%02x", flags);
897
898 ptr[0] = 2;
899 ptr[1] = EIR_FLAGS;
900 ptr[2] = flags;
901
902 ad_len += 3;
903 ptr += 3;
904 }
905
906 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
907 ptr[0] = 2;
908 ptr[1] = EIR_TX_POWER;
909 ptr[2] = (u8) hdev->adv_tx_power;
910
911 ad_len += 3;
912 ptr += 3;
913 }
914
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700915 return ad_len;
916}
917
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700918static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700919{
920 struct hci_dev *hdev = req->hdev;
921 struct hci_cp_le_set_adv_data cp;
922 u8 len;
923
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700924 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700925 return;
926
927 memset(&cp, 0, sizeof(cp));
928
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700929 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700930
931 if (hdev->adv_data_len == len &&
932 memcmp(cp.data, hdev->adv_data, len) == 0)
933 return;
934
935 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
936 hdev->adv_data_len = len;
937
938 cp.length = len;
939
940 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
941}
942
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300943int mgmt_update_adv_data(struct hci_dev *hdev)
944{
945 struct hci_request req;
946
947 hci_req_init(&req, hdev);
948 update_adv_data(&req);
949
950 return hci_req_run(&req, NULL);
951}
952
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300953static void create_eir(struct hci_dev *hdev, u8 *data)
954{
955 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300956 size_t name_len;
957
958 name_len = strlen(hdev->dev_name);
959
960 if (name_len > 0) {
961 /* EIR Data type */
962 if (name_len > 48) {
963 name_len = 48;
964 ptr[1] = EIR_NAME_SHORT;
965 } else
966 ptr[1] = EIR_NAME_COMPLETE;
967
968 /* EIR Data length */
969 ptr[0] = name_len + 1;
970
971 memcpy(ptr + 2, hdev->dev_name, name_len);
972
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973 ptr += (name_len + 2);
974 }
975
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100976 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700977 ptr[0] = 2;
978 ptr[1] = EIR_TX_POWER;
979 ptr[2] = (u8) hdev->inq_tx_power;
980
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700981 ptr += 3;
982 }
983
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700984 if (hdev->devid_source > 0) {
985 ptr[0] = 9;
986 ptr[1] = EIR_DEVICE_ID;
987
988 put_unaligned_le16(hdev->devid_source, ptr + 2);
989 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
990 put_unaligned_le16(hdev->devid_product, ptr + 6);
991 put_unaligned_le16(hdev->devid_version, ptr + 8);
992
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700993 ptr += 10;
994 }
995
Johan Hedberg213202e2013-01-27 00:31:33 +0200996 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200997 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200998 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300999}
1000
Johan Hedberg890ea892013-03-15 17:06:52 -05001001static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001002{
Johan Hedberg890ea892013-03-15 17:06:52 -05001003 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001004 struct hci_cp_write_eir cp;
1005
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001006 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001007 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001008
Johan Hedberg976eb202012-10-24 21:12:01 +03001009 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001011
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001012 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001013 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001014
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001015 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001017
1018 memset(&cp, 0, sizeof(cp));
1019
1020 create_eir(hdev, cp.data);
1021
1022 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001024
1025 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1026
Johan Hedberg890ea892013-03-15 17:06:52 -05001027 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001028}
1029
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030static u8 get_service_classes(struct hci_dev *hdev)
1031{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001032 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033 u8 val = 0;
1034
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001035 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001036 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001037
1038 return val;
1039}
1040
Johan Hedberg890ea892013-03-15 17:06:52 -05001041static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001042{
Johan Hedberg890ea892013-03-15 17:06:52 -05001043 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001044 u8 cod[3];
1045
1046 BT_DBG("%s", hdev->name);
1047
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001048 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001049 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001050
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001051 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001052 return;
1053
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001054 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001055 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001056
1057 cod[0] = hdev->minor_class;
1058 cod[1] = hdev->major_class;
1059 cod[2] = get_service_classes(hdev);
1060
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001061 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001062 cod[1] |= 0x20;
1063
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001064 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001065 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001066
Johan Hedberg890ea892013-03-15 17:06:52 -05001067 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001068}
1069
Johan Hedberga4858cb2014-02-25 19:56:31 +02001070static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001071{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001072 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001073
1074 /* If there's a pending mgmt command the flag will not yet have
1075 * it's final value, so check for this first.
1076 */
1077 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1078 if (cmd) {
1079 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001081 }
1082
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001083 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001084}
1085
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001086static void disable_advertising(struct hci_request *req)
1087{
1088 u8 enable = 0x00;
1089
1090 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1091}
1092
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001093static void enable_advertising(struct hci_request *req)
1094{
1095 struct hci_dev *hdev = req->hdev;
1096 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001097 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001098 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001099
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001100 if (hci_conn_num(hdev, LE_LINK) > 0)
1101 return;
1102
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001103 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001104 disable_advertising(req);
1105
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001106 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001107 * hci_update_random_address knows that it's safe to go ahead
1108 * and write a new random address. The flag will be set back on
1109 * as soon as the SET_ADV_ENABLE HCI command completes.
1110 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001111 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001112
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001113 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001114 connectable = true;
1115 else
1116 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001117
Johan Hedberga4858cb2014-02-25 19:56:31 +02001118 /* Set require_privacy to true only when non-connectable
1119 * advertising is used. In that case it is fine to use a
1120 * non-resolvable private address.
1121 */
1122 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001123 return;
1124
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001125 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001126 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1127 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001128 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001129 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001130 cp.channel_map = hdev->le_adv_channel_map;
1131
1132 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1133
1134 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1135}
1136
Johan Hedberg7d785252011-12-15 00:47:39 +02001137static void service_cache_off(struct work_struct *work)
1138{
1139 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001140 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001141 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001142
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001143 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001144 return;
1145
Johan Hedberg890ea892013-03-15 17:06:52 -05001146 hci_req_init(&req, hdev);
1147
Johan Hedberg7d785252011-12-15 00:47:39 +02001148 hci_dev_lock(hdev);
1149
Johan Hedberg890ea892013-03-15 17:06:52 -05001150 update_eir(&req);
1151 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001152
1153 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001154
1155 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001156}
1157
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001158static void rpa_expired(struct work_struct *work)
1159{
1160 struct hci_dev *hdev = container_of(work, struct hci_dev,
1161 rpa_expired.work);
1162 struct hci_request req;
1163
1164 BT_DBG("");
1165
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 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001192 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001193}
1194
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001195static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001196 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001197{
1198 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001199
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001200 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001201
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001202 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001203
Johan Hedberg03811012010-12-08 00:21:06 +02001204 memset(&rp, 0, sizeof(rp));
1205
Johan Hedberg03811012010-12-08 00:21:06 +02001206 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001207
1208 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001209 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001210
1211 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1212 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1213
1214 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001215
1216 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001217 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001218
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001219 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001220
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001221 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1222 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001223}
1224
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001225static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001226{
1227 sock_put(cmd->sk);
1228 kfree(cmd->param);
1229 kfree(cmd);
1230}
1231
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001232static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
1233 struct hci_dev *hdev,
1234 void *data, u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001235{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001236 struct mgmt_pending_cmd *cmd;
Johan Hedberg03811012010-12-08 00:21:06 +02001237
Johan Hedbergfca20012014-06-28 17:54:05 +03001238 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001239 if (!cmd)
1240 return NULL;
1241
1242 cmd->opcode = opcode;
1243 cmd->index = hdev->id;
1244
Johan Hedberg323b0b82014-12-05 13:36:01 +02001245 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001246 if (!cmd->param) {
1247 kfree(cmd);
1248 return NULL;
1249 }
1250
Johan Hedberg323b0b82014-12-05 13:36:01 +02001251 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001252
1253 cmd->sk = sk;
1254 sock_hold(sk);
1255
1256 list_add(&cmd->list, &hdev->mgmt_pending);
1257
1258 return cmd;
1259}
1260
1261static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001262 void (*cb)(struct mgmt_pending_cmd *cmd,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001263 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001264 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001265{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001266 struct mgmt_pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001267
Andre Guedesa3d09352013-02-01 11:21:30 -03001268 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001269 if (opcode > 0 && cmd->opcode != opcode)
1270 continue;
1271
1272 cb(cmd, data);
1273 }
1274}
1275
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001276static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001277{
1278 list_del(&cmd->list);
1279 mgmt_pending_free(cmd);
1280}
1281
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001282static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001283{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001284 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001285
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001286 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1287 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001288}
1289
Marcel Holtmann1904a852015-01-11 13:50:44 -08001290static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001291{
1292 BT_DBG("%s status 0x%02x", hdev->name, status);
1293
Johan Hedberga3172b72014-02-28 09:33:44 +02001294 if (hci_conn_count(hdev) == 0) {
1295 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001296 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001297 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001298}
1299
Johan Hedberg23a48092014-07-08 16:05:06 +03001300static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001301{
1302 struct hci_dev *hdev = req->hdev;
1303 struct hci_cp_remote_name_req_cancel cp;
1304 struct inquiry_entry *e;
1305
1306 switch (hdev->discovery.state) {
1307 case DISCOVERY_FINDING:
1308 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1309 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1310 } else {
1311 cancel_delayed_work(&hdev->le_scan_disable);
1312 hci_req_add_le_scan_disable(req);
1313 }
1314
Johan Hedberg23a48092014-07-08 16:05:06 +03001315 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001316
1317 case DISCOVERY_RESOLVING:
1318 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1319 NAME_PENDING);
1320 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001321 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001322
1323 bacpy(&cp.bdaddr, &e->data.bdaddr);
1324 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1325 &cp);
1326
Johan Hedberg23a48092014-07-08 16:05:06 +03001327 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001328
1329 default:
1330 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001331 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001332 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001333 return true;
1334 }
1335
Johan Hedberg21a60d32014-06-10 14:05:58 +03001336 break;
1337 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001338
1339 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001340}
1341
Johan Hedberg8b064a32014-02-24 14:52:22 +02001342static int clean_up_hci_state(struct hci_dev *hdev)
1343{
1344 struct hci_request req;
1345 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001346 bool discov_stopped;
1347 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001348
1349 hci_req_init(&req, hdev);
1350
1351 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1352 test_bit(HCI_PSCAN, &hdev->flags)) {
1353 u8 scan = 0x00;
1354 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1355 }
1356
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001357 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001358 disable_advertising(&req);
1359
Johan Hedberg23a48092014-07-08 16:05:06 +03001360 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001361
1362 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1363 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001364 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001365
Johan Hedbergc9910d02014-02-27 14:35:12 +02001366 switch (conn->state) {
1367 case BT_CONNECTED:
1368 case BT_CONFIG:
1369 dc.handle = cpu_to_le16(conn->handle);
1370 dc.reason = 0x15; /* Terminated due to Power Off */
1371 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1372 break;
1373 case BT_CONNECT:
1374 if (conn->type == LE_LINK)
1375 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1376 0, NULL);
1377 else if (conn->type == ACL_LINK)
1378 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1379 6, &conn->dst);
1380 break;
1381 case BT_CONNECT2:
1382 bacpy(&rej.bdaddr, &conn->dst);
1383 rej.reason = 0x15; /* Terminated due to Power Off */
1384 if (conn->type == ACL_LINK)
1385 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1386 sizeof(rej), &rej);
1387 else if (conn->type == SCO_LINK)
1388 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1389 sizeof(rej), &rej);
1390 break;
1391 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001392 }
1393
Johan Hedberg23a48092014-07-08 16:05:06 +03001394 err = hci_req_run(&req, clean_up_hci_complete);
1395 if (!err && discov_stopped)
1396 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1397
1398 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001399}
1400
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001401static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001402 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001403{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001404 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001405 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001406 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001407
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001408 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001409
Johan Hedberga7e80f22013-01-09 16:05:19 +02001410 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001411 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1412 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001413
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001414 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001415
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001416 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001417 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1418 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001419 goto failed;
1420 }
1421
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001422 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1423 cancel_delayed_work(&hdev->power_off);
1424
1425 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001426 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1427 data, len);
1428 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001429 goto failed;
1430 }
1431 }
1432
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001433 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001434 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001435 goto failed;
1436 }
1437
Johan Hedberg03811012010-12-08 00:21:06 +02001438 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1439 if (!cmd) {
1440 err = -ENOMEM;
1441 goto failed;
1442 }
1443
Johan Hedberg8b064a32014-02-24 14:52:22 +02001444 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001445 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001446 err = 0;
1447 } else {
1448 /* Disconnect connections, stop scans, etc */
1449 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001450 if (!err)
1451 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1452 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001453
Johan Hedberg8b064a32014-02-24 14:52:22 +02001454 /* ENODATA means there were no HCI commands queued */
1455 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001456 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001457 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1458 err = 0;
1459 }
1460 }
Johan Hedberg03811012010-12-08 00:21:06 +02001461
1462failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001463 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001464 return err;
1465}
1466
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001467static int new_settings(struct hci_dev *hdev, struct sock *skip)
1468{
1469 __le32 ev;
1470
1471 ev = cpu_to_le32(get_current_settings(hdev));
1472
1473 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1474}
1475
Johan Hedberg91a668b2014-07-09 13:28:26 +03001476int mgmt_new_settings(struct hci_dev *hdev)
1477{
1478 return new_settings(hdev, NULL);
1479}
1480
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001481struct cmd_lookup {
1482 struct sock *sk;
1483 struct hci_dev *hdev;
1484 u8 mgmt_status;
1485};
1486
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001487static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001488{
1489 struct cmd_lookup *match = data;
1490
1491 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1492
1493 list_del(&cmd->list);
1494
1495 if (match->sk == NULL) {
1496 match->sk = cmd->sk;
1497 sock_hold(match->sk);
1498 }
1499
1500 mgmt_pending_free(cmd);
1501}
1502
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001503static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001504{
1505 u8 *status = data;
1506
Johan Hedberga69e8372015-03-06 21:08:53 +02001507 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001508 mgmt_pending_remove(cmd);
1509}
1510
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001511static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001512{
1513 if (cmd->cmd_complete) {
1514 u8 *status = data;
1515
1516 cmd->cmd_complete(cmd, *status);
1517 mgmt_pending_remove(cmd);
1518
1519 return;
1520 }
1521
1522 cmd_status_rsp(cmd, data);
1523}
1524
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001525static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001526{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001527 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1528 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001529}
1530
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001531static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001532{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001533 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1534 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001535}
1536
Johan Hedberge6fe7982013-10-02 15:45:22 +03001537static u8 mgmt_bredr_support(struct hci_dev *hdev)
1538{
1539 if (!lmp_bredr_capable(hdev))
1540 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001541 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001542 return MGMT_STATUS_REJECTED;
1543 else
1544 return MGMT_STATUS_SUCCESS;
1545}
1546
1547static u8 mgmt_le_support(struct hci_dev *hdev)
1548{
1549 if (!lmp_le_capable(hdev))
1550 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001551 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001552 return MGMT_STATUS_REJECTED;
1553 else
1554 return MGMT_STATUS_SUCCESS;
1555}
1556
Marcel Holtmann1904a852015-01-11 13:50:44 -08001557static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1558 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001559{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001560 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001561 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001562 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001563 bool changed;
1564
1565 BT_DBG("status 0x%02x", status);
1566
1567 hci_dev_lock(hdev);
1568
1569 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1570 if (!cmd)
1571 goto unlock;
1572
1573 if (status) {
1574 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001575 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001576 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001577 goto remove_cmd;
1578 }
1579
1580 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001581 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001582 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1583 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001584
1585 if (hdev->discov_timeout > 0) {
1586 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1587 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1588 to);
1589 }
1590 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001591 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1592 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001593 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001594
1595 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1596
1597 if (changed)
1598 new_settings(hdev, cmd->sk);
1599
Marcel Holtmann970ba522013-10-15 06:33:57 -07001600 /* When the discoverable mode gets changed, make sure
1601 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001602 * bit correctly set. Also update page scan based on whitelist
1603 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001604 */
1605 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001606 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001607 update_class(&req);
1608 hci_req_run(&req, NULL);
1609
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001610remove_cmd:
1611 mgmt_pending_remove(cmd);
1612
1613unlock:
1614 hci_dev_unlock(hdev);
1615}
1616
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001617static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001618 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001619{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001620 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001621 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001622 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001623 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001624 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001625 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001626
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001628
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001629 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1630 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001631 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1632 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001633
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001634 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001635 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1636 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001637
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001638 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001639
1640 /* Disabling discoverable requires that no timeout is set,
1641 * and enabling limited discoverable requires a timeout.
1642 */
1643 if ((cp->val == 0x00 && timeout > 0) ||
1644 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001645 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1646 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001647
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001648 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001649
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001650 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001651 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1652 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001653 goto failed;
1654 }
1655
1656 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001657 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001658 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1659 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001660 goto failed;
1661 }
1662
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001663 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001664 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1665 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001666 goto failed;
1667 }
1668
1669 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001670 bool changed = false;
1671
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001672 /* Setting limited discoverable when powered off is
1673 * not a valid operation since it requires a timeout
1674 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1675 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001676 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001677 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1678 changed = true;
1679 }
1680
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001681 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001682 if (err < 0)
1683 goto failed;
1684
1685 if (changed)
1686 err = new_settings(hdev, sk);
1687
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001688 goto failed;
1689 }
1690
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001691 /* If the current mode is the same, then just update the timeout
1692 * value with the new value. And if only the timeout gets updated,
1693 * then no need for any HCI transactions.
1694 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001695 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1696 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1697 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001698 cancel_delayed_work(&hdev->discov_off);
1699 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001700
Marcel Holtmann36261542013-10-15 08:28:51 -07001701 if (cp->val && hdev->discov_timeout > 0) {
1702 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001703 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001704 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001705 }
1706
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001707 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001708 goto failed;
1709 }
1710
1711 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1712 if (!cmd) {
1713 err = -ENOMEM;
1714 goto failed;
1715 }
1716
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 /* Cancel any potential discoverable timeout that might be
1718 * still active and store new timeout value. The arming of
1719 * the timeout happens in the complete handler.
1720 */
1721 cancel_delayed_work(&hdev->discov_off);
1722 hdev->discov_timeout = timeout;
1723
Johan Hedbergb456f872013-10-19 23:38:22 +03001724 /* Limited discoverable mode */
1725 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001726 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001727 else
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001730 hci_req_init(&req, hdev);
1731
Johan Hedberg9a43e252013-10-20 19:00:07 +03001732 /* The procedure for LE-only controllers is much simpler - just
1733 * update the advertising data.
1734 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001735 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001736 goto update_ad;
1737
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001738 scan = SCAN_PAGE;
1739
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001740 if (cp->val) {
1741 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001742
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001743 if (cp->val == 0x02) {
1744 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001745 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001746 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1747 hci_cp.iac_lap[1] = 0x8b;
1748 hci_cp.iac_lap[2] = 0x9e;
1749 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1750 hci_cp.iac_lap[4] = 0x8b;
1751 hci_cp.iac_lap[5] = 0x9e;
1752 } else {
1753 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001754 hci_cp.num_iac = 1;
1755 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1756 hci_cp.iac_lap[1] = 0x8b;
1757 hci_cp.iac_lap[2] = 0x9e;
1758 }
1759
1760 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1761 (hci_cp.num_iac * 3) + 1, &hci_cp);
1762
1763 scan |= SCAN_INQUIRY;
1764 } else {
1765 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1766 }
1767
1768 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001769
Johan Hedberg9a43e252013-10-20 19:00:07 +03001770update_ad:
1771 update_adv_data(&req);
1772
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001773 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001774 if (err < 0)
1775 mgmt_pending_remove(cmd);
1776
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001777failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001778 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001779 return err;
1780}
1781
Johan Hedberg406d7802013-03-15 17:07:09 -05001782static void write_fast_connectable(struct hci_request *req, bool enable)
1783{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001784 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001785 struct hci_cp_write_page_scan_activity acp;
1786 u8 type;
1787
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001788 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001789 return;
1790
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001791 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1792 return;
1793
Johan Hedberg406d7802013-03-15 17:07:09 -05001794 if (enable) {
1795 type = PAGE_SCAN_TYPE_INTERLACED;
1796
1797 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001798 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001799 } else {
1800 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1801
1802 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001803 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001804 }
1805
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001806 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001807
Johan Hedbergbd98b992013-03-15 17:07:13 -05001808 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1809 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1810 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1811 sizeof(acp), &acp);
1812
1813 if (hdev->page_scan_type != type)
1814 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001815}
1816
Marcel Holtmann1904a852015-01-11 13:50:44 -08001817static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1818 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001819{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001820 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001822 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823
1824 BT_DBG("status 0x%02x", status);
1825
1826 hci_dev_lock(hdev);
1827
1828 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1829 if (!cmd)
1830 goto unlock;
1831
Johan Hedberg37438c12013-10-14 16:20:05 +03001832 if (status) {
1833 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001834 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001835 goto remove_cmd;
1836 }
1837
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001838 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001839 if (cp->val) {
1840 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1841 &hdev->dev_flags);
1842 discov_changed = false;
1843 } else {
1844 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1845 &hdev->dev_flags);
1846 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1847 &hdev->dev_flags);
1848 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001849
Johan Hedberg2b76f452013-03-15 17:07:04 -05001850 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1851
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001852 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001853 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001854 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001855 if (discov_changed)
1856 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001857 hci_update_background_scan(hdev);
1858 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001859
Johan Hedberg37438c12013-10-14 16:20:05 +03001860remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001861 mgmt_pending_remove(cmd);
1862
1863unlock:
1864 hci_dev_unlock(hdev);
1865}
1866
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001867static int set_connectable_update_settings(struct hci_dev *hdev,
1868 struct sock *sk, u8 val)
1869{
1870 bool changed = false;
1871 int err;
1872
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001873 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001874 changed = true;
1875
1876 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001877 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001878 } else {
1879 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1880 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1881 }
1882
1883 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1884 if (err < 0)
1885 return err;
1886
Johan Hedberg562064e2014-07-08 16:35:34 +03001887 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001888 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001889 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001890 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001891 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001892
1893 return 0;
1894}
1895
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001896static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001897 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001898{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001899 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001900 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001901 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001902 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001903 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001904
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001905 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001906
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001907 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1908 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001909 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1910 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001911
Johan Hedberga7e80f22013-01-09 16:05:19 +02001912 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001913 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1914 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001915
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001916 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001917
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001918 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001919 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001920 goto failed;
1921 }
1922
1923 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001924 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001925 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1926 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001927 goto failed;
1928 }
1929
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001930 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1931 if (!cmd) {
1932 err = -ENOMEM;
1933 goto failed;
1934 }
1935
Johan Hedberg2b76f452013-03-15 17:07:04 -05001936 hci_req_init(&req, hdev);
1937
Johan Hedberg9a43e252013-10-20 19:00:07 +03001938 /* If BR/EDR is not enabled and we disable advertising as a
1939 * by-product of disabling connectable, we need to update the
1940 * advertising flags.
1941 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001942 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03001943 if (!cp->val) {
1944 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1945 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1946 }
1947 update_adv_data(&req);
1948 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001949 if (cp->val) {
1950 scan = SCAN_PAGE;
1951 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001952 /* If we don't have any whitelist entries just
1953 * disable all scanning. If there are entries
1954 * and we had both page and inquiry scanning
1955 * enabled then fall back to only page scanning.
1956 * Otherwise no changes are needed.
1957 */
1958 if (list_empty(&hdev->whitelist))
1959 scan = SCAN_DISABLED;
1960 else if (test_bit(HCI_ISCAN, &hdev->flags))
1961 scan = SCAN_PAGE;
1962 else
1963 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001964
1965 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001966 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001967 cancel_delayed_work(&hdev->discov_off);
1968 }
1969
1970 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1971 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001972
Johan Hedberg3bd27242014-07-28 20:53:58 +03001973no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03001974 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001975 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001976 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001977
Johan Hedberg2b76f452013-03-15 17:07:04 -05001978 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001979 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001981 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001982 err = set_connectable_update_settings(hdev, sk,
1983 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001984 goto failed;
1985 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
1987failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001988 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989 return err;
1990}
1991
Johan Hedbergb2939472014-07-30 09:22:23 +03001992static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001993 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001994{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001995 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001996 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001997 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001998
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001999 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002000
Johan Hedberga7e80f22013-01-09 16:05:19 +02002001 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002002 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2003 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002004
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002005 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002006
2007 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002008 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002009 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002010 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002011
Johan Hedbergb2939472014-07-30 09:22:23 +03002012 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002013 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002014 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002015
Marcel Holtmann55594352013-10-06 16:11:57 -07002016 if (changed)
2017 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002018
Marcel Holtmann55594352013-10-06 16:11:57 -07002019unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002020 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002021 return err;
2022}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002023
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002024static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2025 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002026{
2027 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002028 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002029 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002030 int err;
2031
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002032 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002033
Johan Hedberge6fe7982013-10-02 15:45:22 +03002034 status = mgmt_bredr_support(hdev);
2035 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002036 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2037 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002038
Johan Hedberga7e80f22013-01-09 16:05:19 +02002039 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002040 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2041 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002042
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002043 hci_dev_lock(hdev);
2044
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002045 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002046 bool changed = false;
2047
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002048 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002049 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2050 changed = true;
2051 }
2052
2053 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2054 if (err < 0)
2055 goto failed;
2056
2057 if (changed)
2058 err = new_settings(hdev, sk);
2059
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002060 goto failed;
2061 }
2062
2063 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002064 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2065 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002066 goto failed;
2067 }
2068
2069 val = !!cp->val;
2070
2071 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2072 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2073 goto failed;
2074 }
2075
2076 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2077 if (!cmd) {
2078 err = -ENOMEM;
2079 goto failed;
2080 }
2081
2082 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2083 if (err < 0) {
2084 mgmt_pending_remove(cmd);
2085 goto failed;
2086 }
2087
2088failed:
2089 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002090 return err;
2091}
2092
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002093static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002094{
2095 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002096 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002097 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002098 int err;
2099
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002100 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002101
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002102 status = mgmt_bredr_support(hdev);
2103 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002104 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002105
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002106 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002107 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2108 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002109
Johan Hedberga7e80f22013-01-09 16:05:19 +02002110 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002111 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2112 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002113
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002114 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002115
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002116 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002117 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002118
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002119 if (cp->val) {
2120 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2121 &hdev->dev_flags);
2122 } else {
2123 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2124 &hdev->dev_flags);
2125 if (!changed)
2126 changed = test_and_clear_bit(HCI_HS_ENABLED,
2127 &hdev->dev_flags);
2128 else
2129 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002130 }
2131
2132 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2133 if (err < 0)
2134 goto failed;
2135
2136 if (changed)
2137 err = new_settings(hdev, sk);
2138
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002139 goto failed;
2140 }
2141
Johan Hedberg94d52da2015-02-19 17:38:06 +02002142 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002143 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2144 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002145 goto failed;
2146 }
2147
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002148 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002149 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2150 goto failed;
2151 }
2152
2153 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2154 if (!cmd) {
2155 err = -ENOMEM;
2156 goto failed;
2157 }
2158
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002159 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002160 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2161 sizeof(cp->val), &cp->val);
2162
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002163 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002164 if (err < 0) {
2165 mgmt_pending_remove(cmd);
2166 goto failed;
2167 }
2168
2169failed:
2170 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002171 return err;
2172}
2173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002174static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002175{
2176 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002177 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002178 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002179 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002181 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002182
Johan Hedberge6fe7982013-10-02 15:45:22 +03002183 status = mgmt_bredr_support(hdev);
2184 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002185 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002186
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002187 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002188 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2189 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002190
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002191 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002192 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2193 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002194
Johan Hedberga7e80f22013-01-09 16:05:19 +02002195 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002196 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2197 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002198
Marcel Holtmannee392692013-10-01 22:59:23 -07002199 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002200
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002201 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002202 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2203 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002204 goto unlock;
2205 }
2206
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002207 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002208 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002209 } else {
2210 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002211 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2212 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002213 goto unlock;
2214 }
2215
Marcel Holtmannee392692013-10-01 22:59:23 -07002216 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002217 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002218
2219 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2220 if (err < 0)
2221 goto unlock;
2222
2223 if (changed)
2224 err = new_settings(hdev, sk);
2225
2226unlock:
2227 hci_dev_unlock(hdev);
2228 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002229}
2230
Marcel Holtmann1904a852015-01-11 13:50:44 -08002231static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002232{
2233 struct cmd_lookup match = { NULL, hdev };
2234
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302235 hci_dev_lock(hdev);
2236
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002237 if (status) {
2238 u8 mgmt_err = mgmt_status(status);
2239
2240 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2241 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302242 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002243 }
2244
2245 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2246
2247 new_settings(hdev, match.sk);
2248
2249 if (match.sk)
2250 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002251
2252 /* Make sure the controller has a good default for
2253 * advertising data. Restrict the update to when LE
2254 * has actually been enabled. During power on, the
2255 * update in powered_update_hci will take care of it.
2256 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002257 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002258 struct hci_request req;
2259
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002260 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002261 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002262 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002263 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002264 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002265 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302266
2267unlock:
2268 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002269}
2270
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002271static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002272{
2273 struct mgmt_mode *cp = data;
2274 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002275 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002276 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002277 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002278 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002279
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002280 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002281
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002282 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002283 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2284 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002285
Johan Hedberga7e80f22013-01-09 16:05:19 +02002286 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002287 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2288 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002289
Johan Hedbergc73eee92013-04-19 18:35:21 +03002290 /* LE-only devices do not allow toggling LE on/off */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002291 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002292 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2293 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002294
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002295 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002296
2297 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002298 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002300 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 bool changed = false;
2302
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002303 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002304 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2305 changed = true;
2306 }
2307
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002308 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002309 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002310 changed = true;
2311 }
2312
Johan Hedberg06199cf2012-02-22 16:37:11 +02002313 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2314 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002315 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002316
2317 if (changed)
2318 err = new_settings(hdev, sk);
2319
Johan Hedberg1de028c2012-02-29 19:55:35 -08002320 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321 }
2322
Johan Hedberg4375f102013-09-25 13:26:10 +03002323 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2324 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002325 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2326 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002327 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002328 }
2329
2330 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2331 if (!cmd) {
2332 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002333 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002334 }
2335
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002336 hci_req_init(&req, hdev);
2337
Johan Hedberg06199cf2012-02-22 16:37:11 +02002338 memset(&hci_cp, 0, sizeof(hci_cp));
2339
2340 if (val) {
2341 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002342 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002343 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002344 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002345 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002346 }
2347
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002348 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2349 &hci_cp);
2350
2351 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302352 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002353 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002354
Johan Hedberg1de028c2012-02-29 19:55:35 -08002355unlock:
2356 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002357 return err;
2358}
2359
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002360/* This is a helper function to test for pending mgmt commands that can
2361 * cause CoD or EIR HCI commands. We can only allow one such pending
2362 * mgmt command at a time since otherwise we cannot easily track what
2363 * the current values are, will be, and based on that calculate if a new
2364 * HCI command needs to be sent and if yes with what value.
2365 */
2366static bool pending_eir_or_class(struct hci_dev *hdev)
2367{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002368 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002369
2370 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2371 switch (cmd->opcode) {
2372 case MGMT_OP_ADD_UUID:
2373 case MGMT_OP_REMOVE_UUID:
2374 case MGMT_OP_SET_DEV_CLASS:
2375 case MGMT_OP_SET_POWERED:
2376 return true;
2377 }
2378 }
2379
2380 return false;
2381}
2382
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002383static const u8 bluetooth_base_uuid[] = {
2384 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2385 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2386};
2387
2388static u8 get_uuid_size(const u8 *uuid)
2389{
2390 u32 val;
2391
2392 if (memcmp(uuid, bluetooth_base_uuid, 12))
2393 return 128;
2394
2395 val = get_unaligned_le32(&uuid[12]);
2396 if (val > 0xffff)
2397 return 32;
2398
2399 return 16;
2400}
2401
Johan Hedberg92da6092013-03-15 17:06:55 -05002402static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2403{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002404 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002405
2406 hci_dev_lock(hdev);
2407
2408 cmd = mgmt_pending_find(mgmt_op, hdev);
2409 if (!cmd)
2410 goto unlock;
2411
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002412 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2413 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002414
2415 mgmt_pending_remove(cmd);
2416
2417unlock:
2418 hci_dev_unlock(hdev);
2419}
2420
Marcel Holtmann1904a852015-01-11 13:50:44 -08002421static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002422{
2423 BT_DBG("status 0x%02x", status);
2424
2425 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2426}
2427
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002428static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002429{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002430 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002431 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002432 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002433 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002434 int err;
2435
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002436 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002437
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002438 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002439
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002440 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002441 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2442 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002443 goto failed;
2444 }
2445
Andre Guedes92c4c202012-06-07 19:05:44 -03002446 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447 if (!uuid) {
2448 err = -ENOMEM;
2449 goto failed;
2450 }
2451
2452 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002453 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002454 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002455
Johan Hedbergde66aa62013-01-27 00:31:27 +02002456 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002457
Johan Hedberg890ea892013-03-15 17:06:52 -05002458 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002459
Johan Hedberg890ea892013-03-15 17:06:52 -05002460 update_class(&req);
2461 update_eir(&req);
2462
Johan Hedberg92da6092013-03-15 17:06:55 -05002463 err = hci_req_run(&req, add_uuid_complete);
2464 if (err < 0) {
2465 if (err != -ENODATA)
2466 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002467
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002468 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2469 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002470 goto failed;
2471 }
2472
2473 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002474 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002475 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002476 goto failed;
2477 }
2478
2479 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480
2481failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002482 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002483 return err;
2484}
2485
Johan Hedberg24b78d02012-02-23 23:24:30 +02002486static bool enable_service_cache(struct hci_dev *hdev)
2487{
2488 if (!hdev_is_powered(hdev))
2489 return false;
2490
2491 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002492 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2493 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002494 return true;
2495 }
2496
2497 return false;
2498}
2499
Marcel Holtmann1904a852015-01-11 13:50:44 -08002500static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002501{
2502 BT_DBG("status 0x%02x", status);
2503
2504 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2505}
2506
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002507static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002508 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002509{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002510 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002511 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002512 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002513 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg890ea892013-03-15 17:06:52 -05002514 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002515 int err, found;
2516
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002517 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002518
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002519 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002521 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002522 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2523 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002524 goto unlock;
2525 }
2526
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002527 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002528 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002529
Johan Hedberg24b78d02012-02-23 23:24:30 +02002530 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002531 err = mgmt_cmd_complete(sk, hdev->id,
2532 MGMT_OP_REMOVE_UUID,
2533 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002534 goto unlock;
2535 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002536
Johan Hedberg9246a862012-02-23 21:33:16 +02002537 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002538 }
2539
2540 found = 0;
2541
Johan Hedberg056341c2013-01-27 00:31:30 +02002542 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002543 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2544 continue;
2545
2546 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002547 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002548 found++;
2549 }
2550
2551 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002552 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2553 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002554 goto unlock;
2555 }
2556
Johan Hedberg9246a862012-02-23 21:33:16 +02002557update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002558 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002559
Johan Hedberg890ea892013-03-15 17:06:52 -05002560 update_class(&req);
2561 update_eir(&req);
2562
Johan Hedberg92da6092013-03-15 17:06:55 -05002563 err = hci_req_run(&req, remove_uuid_complete);
2564 if (err < 0) {
2565 if (err != -ENODATA)
2566 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002567
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002568 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2569 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002570 goto unlock;
2571 }
2572
2573 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002574 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002575 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002576 goto unlock;
2577 }
2578
2579 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002580
2581unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002582 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002583 return err;
2584}
2585
Marcel Holtmann1904a852015-01-11 13:50:44 -08002586static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002587{
2588 BT_DBG("status 0x%02x", status);
2589
2590 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2591}
2592
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002593static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002594 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002595{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002596 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002597 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002598 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002599 int err;
2600
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002601 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002602
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002603 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002604 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2605 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002606
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002607 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002608
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002609 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002610 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2611 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002612 goto unlock;
2613 }
2614
2615 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002616 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2617 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002618 goto unlock;
2619 }
2620
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002621 hdev->major_class = cp->major;
2622 hdev->minor_class = cp->minor;
2623
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002624 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002625 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2626 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002627 goto unlock;
2628 }
2629
Johan Hedberg890ea892013-03-15 17:06:52 -05002630 hci_req_init(&req, hdev);
2631
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002632 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002633 hci_dev_unlock(hdev);
2634 cancel_delayed_work_sync(&hdev->service_cache);
2635 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002636 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002637 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002638
Johan Hedberg890ea892013-03-15 17:06:52 -05002639 update_class(&req);
2640
Johan Hedberg92da6092013-03-15 17:06:55 -05002641 err = hci_req_run(&req, set_class_complete);
2642 if (err < 0) {
2643 if (err != -ENODATA)
2644 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002645
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002646 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2647 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002648 goto unlock;
2649 }
2650
2651 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002652 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002653 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002654 goto unlock;
2655 }
2656
2657 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002658
Johan Hedbergb5235a62012-02-21 14:32:24 +02002659unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002660 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002661 return err;
2662}
2663
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002664static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002665 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002666{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002667 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002668 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2669 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002670 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002671 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002672 int i;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002673
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002674 BT_DBG("request for %s", hdev->name);
2675
2676 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002677 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2678 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002679
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002680 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002681 if (key_count > max_key_count) {
2682 BT_ERR("load_link_keys: too big key_count value %u",
2683 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002684 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2685 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002686 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002687
Johan Hedberg86742e12011-11-07 23:13:38 +02002688 expected_len = sizeof(*cp) + key_count *
2689 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002690 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002691 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002692 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002693 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2694 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002695 }
2696
Johan Hedberg4ae14302013-01-20 14:27:13 +02002697 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002698 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2699 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002700
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002701 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002702 key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002703
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002704 for (i = 0; i < key_count; i++) {
2705 struct mgmt_link_key_info *key = &cp->keys[i];
2706
Marcel Holtmann8e991132014-01-10 02:07:25 -08002707 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002708 return mgmt_cmd_status(sk, hdev->id,
2709 MGMT_OP_LOAD_LINK_KEYS,
2710 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002711 }
2712
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002713 hci_dev_lock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002714
2715 hci_link_keys_clear(hdev);
2716
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002717 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002718 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2719 &hdev->dev_flags);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002720 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002721 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2722 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002723
2724 if (changed)
2725 new_settings(hdev, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002726
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002727 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002728 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002729
Johan Hedberg58e92932014-06-24 14:00:26 +03002730 /* Always ignore debug keys and require a new pairing if
2731 * the user wants to use them.
2732 */
2733 if (key->type == HCI_LK_DEBUG_COMBINATION)
2734 continue;
2735
Johan Hedberg7652ff62014-06-24 13:15:49 +03002736 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2737 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002738 }
2739
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002740 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002741
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002742 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002743
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002744 return 0;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002745}
2746
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002747static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002748 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002749{
2750 struct mgmt_ev_device_unpaired ev;
2751
2752 bacpy(&ev.addr.bdaddr, bdaddr);
2753 ev.addr.type = addr_type;
2754
2755 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002757}
2758
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002759static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002760 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002761{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002762 struct mgmt_cp_unpair_device *cp = data;
2763 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002764 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002765 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002766 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002767 int err;
2768
Johan Hedberga8a1d192011-11-10 15:54:38 +02002769 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002770 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2771 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002772
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002773 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002774 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2775 MGMT_STATUS_INVALID_PARAMS,
2776 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002777
Johan Hedberg118da702013-01-20 14:27:20 +02002778 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002779 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2780 MGMT_STATUS_INVALID_PARAMS,
2781 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002782
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002783 hci_dev_lock(hdev);
2784
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002785 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002786 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2787 MGMT_STATUS_NOT_POWERED, &rp,
2788 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002789 goto unlock;
2790 }
2791
Johan Hedberge0b2b272014-02-18 17:14:31 +02002792 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002793 /* If disconnection is requested, then look up the
2794 * connection. If the remote device is connected, it
2795 * will be later used to terminate the link.
2796 *
2797 * Setting it to NULL explicitly will cause no
2798 * termination of the link.
2799 */
2800 if (cp->disconnect)
2801 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2802 &cp->addr.bdaddr);
2803 else
2804 conn = NULL;
2805
Johan Hedberg124f6e32012-02-09 13:50:12 +02002806 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002807 } else {
2808 u8 addr_type;
2809
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002810 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2811 &cp->addr.bdaddr);
2812 if (conn) {
2813 /* Defer clearing up the connection parameters
2814 * until closing to give a chance of keeping
2815 * them if a repairing happens.
2816 */
2817 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2818
2819 /* If disconnection is not requested, then
2820 * clear the connection variable so that the
2821 * link is not terminated.
2822 */
2823 if (!cp->disconnect)
2824 conn = NULL;
2825 }
2826
Johan Hedberge0b2b272014-02-18 17:14:31 +02002827 if (cp->addr.type == BDADDR_LE_PUBLIC)
2828 addr_type = ADDR_LE_DEV_PUBLIC;
2829 else
2830 addr_type = ADDR_LE_DEV_RANDOM;
2831
Johan Hedberga7ec7332014-02-18 17:14:35 +02002832 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2833
Johan Hedberge0b2b272014-02-18 17:14:31 +02002834 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2835 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002836
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002837 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002838 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2839 MGMT_STATUS_NOT_PAIRED, &rp,
2840 sizeof(rp));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002841 goto unlock;
2842 }
2843
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002844 /* If the connection variable is set, then termination of the
2845 * link is requested.
2846 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002847 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002848 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2849 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002850 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002851 goto unlock;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002852 }
2853
Johan Hedberg124f6e32012-02-09 13:50:12 +02002854 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002855 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002856 if (!cmd) {
2857 err = -ENOMEM;
2858 goto unlock;
2859 }
2860
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002861 cmd->cmd_complete = addr_cmd_complete;
2862
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002863 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002864 dc.reason = 0x13; /* Remote User Terminated Connection */
2865 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2866 if (err < 0)
2867 mgmt_pending_remove(cmd);
2868
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002869unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002870 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002871 return err;
2872}
2873
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002874static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002875 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002876{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002877 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002878 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002879 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002880 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002881 int err;
2882
2883 BT_DBG("");
2884
Johan Hedberg06a63b12013-01-20 14:27:21 +02002885 memset(&rp, 0, sizeof(rp));
2886 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2887 rp.addr.type = cp->addr.type;
2888
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002889 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002890 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2891 MGMT_STATUS_INVALID_PARAMS,
2892 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002893
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002894 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002895
2896 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002897 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2898 MGMT_STATUS_NOT_POWERED, &rp,
2899 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002900 goto failed;
2901 }
2902
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002903 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002904 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2905 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002906 goto failed;
2907 }
2908
Andre Guedes591f47f2012-04-24 21:02:49 -03002909 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002910 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2911 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002912 else
2913 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002914
Vishal Agarwalf9607272012-06-13 05:32:43 +05302915 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002916 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2917 MGMT_STATUS_NOT_CONNECTED, &rp,
2918 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002919 goto failed;
2920 }
2921
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002922 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002923 if (!cmd) {
2924 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002925 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002926 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002927
Johan Hedbergf5818c22014-12-05 13:36:02 +02002928 cmd->cmd_complete = generic_cmd_complete;
2929
Johan Hedberge3f2f922014-08-18 20:33:33 +03002930 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002931 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002932 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002933
2934failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002935 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002936 return err;
2937}
2938
Andre Guedes57c14772012-04-24 21:02:50 -03002939static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002940{
2941 switch (link_type) {
2942 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002943 switch (addr_type) {
2944 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002945 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002946
Johan Hedberg48264f02011-11-09 13:58:58 +02002947 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002948 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002949 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002950 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002951
Johan Hedberg4c659c32011-11-07 23:13:39 +02002952 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002953 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002954 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002955 }
2956}
2957
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002958static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2959 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002960{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002961 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002962 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002963 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002964 int err;
2965 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002966
2967 BT_DBG("");
2968
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002969 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002970
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002971 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002972 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2973 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002974 goto unlock;
2975 }
2976
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002977 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002978 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2979 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002980 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002981 }
2982
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002983 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002984 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002985 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002986 err = -ENOMEM;
2987 goto unlock;
2988 }
2989
Johan Hedberg2784eb42011-01-21 13:56:35 +02002990 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002991 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002992 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2993 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002994 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002995 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002996 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002997 continue;
2998 i++;
2999 }
3000
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003001 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003002
Johan Hedberg4c659c32011-11-07 23:13:39 +02003003 /* Recalculate length in case of filtered SCO connections, etc */
3004 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003005
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003006 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3007 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003008
Johan Hedberga38528f2011-01-22 06:46:43 +02003009 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003010
3011unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003012 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003013 return err;
3014}
3015
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003016static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003017 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003018{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003019 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003020 int err;
3021
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003022 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003023 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003024 if (!cmd)
3025 return -ENOMEM;
3026
Johan Hedbergd8457692012-02-17 14:24:57 +02003027 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003028 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003029 if (err < 0)
3030 mgmt_pending_remove(cmd);
3031
3032 return err;
3033}
3034
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003035static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003036 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003037{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003038 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003039 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003041 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003042 int err;
3043
3044 BT_DBG("");
3045
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003046 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003047
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003048 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003049 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3050 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003051 goto failed;
3052 }
3053
Johan Hedbergd8457692012-02-17 14:24:57 +02003054 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003055 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003056 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3057 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003058 goto failed;
3059 }
3060
3061 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003062 struct mgmt_cp_pin_code_neg_reply ncp;
3063
3064 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003065
3066 BT_ERR("PIN code is not 16 bytes long");
3067
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003068 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003069 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003070 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3071 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003072
3073 goto failed;
3074 }
3075
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003076 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003077 if (!cmd) {
3078 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003079 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003080 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003081
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003082 cmd->cmd_complete = addr_cmd_complete;
3083
Johan Hedbergd8457692012-02-17 14:24:57 +02003084 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003085 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003086 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003087
3088 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3089 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003090 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003091
3092failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003093 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003094 return err;
3095}
3096
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003097static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3098 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003099{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003100 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003101
3102 BT_DBG("");
3103
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003104 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003105 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3106 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003107
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003108 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003109
3110 hdev->io_capability = cp->io_capability;
3111
3112 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003113 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003114
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003115 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003116
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003117 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3118 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003119}
3120
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003121static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003122{
3123 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003124 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003125
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003126 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003127 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3128 continue;
3129
Johan Hedberge9a416b2011-02-19 12:05:56 -03003130 if (cmd->user_data != conn)
3131 continue;
3132
3133 return cmd;
3134 }
3135
3136 return NULL;
3137}
3138
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003139static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003140{
3141 struct mgmt_rp_pair_device rp;
3142 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003143 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003144
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003145 bacpy(&rp.addr.bdaddr, &conn->dst);
3146 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003147
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003148 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3149 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003150
3151 /* So we don't get further callbacks for this connection */
3152 conn->connect_cfm_cb = NULL;
3153 conn->security_cfm_cb = NULL;
3154 conn->disconn_cfm_cb = NULL;
3155
David Herrmann76a68ba2013-04-06 20:28:37 +02003156 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003157
3158 /* The device is paired so there is no need to remove
3159 * its connection parameters anymore.
3160 */
3161 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003162
3163 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003164
3165 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166}
3167
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003168void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3169{
3170 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003171 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003172
3173 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003174 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003175 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003176 mgmt_pending_remove(cmd);
3177 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003178}
3179
Johan Hedberge9a416b2011-02-19 12:05:56 -03003180static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3181{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003182 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003183
3184 BT_DBG("status %u", status);
3185
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003186 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003187 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003188 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003189 return;
3190 }
3191
3192 cmd->cmd_complete(cmd, mgmt_status(status));
3193 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003194}
3195
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003196static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303197{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003198 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303199
3200 BT_DBG("status %u", status);
3201
3202 if (!status)
3203 return;
3204
3205 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003206 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303207 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003208 return;
3209 }
3210
3211 cmd->cmd_complete(cmd, mgmt_status(status));
3212 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303213}
3214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003215static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003216 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003217{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003218 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003219 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003220 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003221 u8 sec_level, auth_type;
3222 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003223 int err;
3224
3225 BT_DBG("");
3226
Szymon Jancf950a30e2013-01-18 12:48:07 +01003227 memset(&rp, 0, sizeof(rp));
3228 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3229 rp.addr.type = cp->addr.type;
3230
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003231 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003232 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3233 MGMT_STATUS_INVALID_PARAMS,
3234 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003235
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003236 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003237 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3238 MGMT_STATUS_INVALID_PARAMS,
3239 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003240
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003241 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003242
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003243 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003244 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3245 MGMT_STATUS_NOT_POWERED, &rp,
3246 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003247 goto unlock;
3248 }
3249
Johan Hedberg55e76b32015-03-10 22:34:40 +02003250 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3251 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3252 MGMT_STATUS_ALREADY_PAIRED, &rp,
3253 sizeof(rp));
3254 goto unlock;
3255 }
3256
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003257 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003258 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003259
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003260 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003261 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3262 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003263 } else {
3264 u8 addr_type;
3265
3266 /* Convert from L2CAP channel address type to HCI address type
3267 */
3268 if (cp->addr.type == BDADDR_LE_PUBLIC)
3269 addr_type = ADDR_LE_DEV_PUBLIC;
3270 else
3271 addr_type = ADDR_LE_DEV_RANDOM;
3272
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003273 /* When pairing a new device, it is expected to remember
3274 * this device for future connections. Adding the connection
3275 * parameter information ahead of time allows tracking
3276 * of the slave preferred values and will speed up any
3277 * further connection establishment.
3278 *
3279 * If connection parameters already exist, then they
3280 * will be kept and this function does nothing.
3281 */
3282 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3283
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003284 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003285 sec_level, HCI_LE_CONN_TIMEOUT,
3286 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003287 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003288
Ville Tervo30e76272011-02-22 16:10:53 -03003289 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003290 int status;
3291
3292 if (PTR_ERR(conn) == -EBUSY)
3293 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003294 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3295 status = MGMT_STATUS_NOT_SUPPORTED;
3296 else if (PTR_ERR(conn) == -ECONNREFUSED)
3297 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003298 else
3299 status = MGMT_STATUS_CONNECT_FAILED;
3300
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003301 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3302 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003303 goto unlock;
3304 }
3305
3306 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003307 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003308 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3309 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003310 goto unlock;
3311 }
3312
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003313 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003314 if (!cmd) {
3315 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003316 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003317 goto unlock;
3318 }
3319
Johan Hedberg04ab2742014-12-05 13:36:04 +02003320 cmd->cmd_complete = pairing_complete;
3321
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003322 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003323 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003324 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003325 conn->security_cfm_cb = pairing_complete_cb;
3326 conn->disconn_cfm_cb = pairing_complete_cb;
3327 } else {
3328 conn->connect_cfm_cb = le_pairing_complete_cb;
3329 conn->security_cfm_cb = le_pairing_complete_cb;
3330 conn->disconn_cfm_cb = le_pairing_complete_cb;
3331 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003332
Johan Hedberge9a416b2011-02-19 12:05:56 -03003333 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003334 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003335
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003336 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003337 hci_conn_security(conn, sec_level, auth_type, true)) {
3338 cmd->cmd_complete(cmd, 0);
3339 mgmt_pending_remove(cmd);
3340 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003341
3342 err = 0;
3343
3344unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003345 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003346 return err;
3347}
3348
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003349static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3350 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003351{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003352 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003353 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003354 struct hci_conn *conn;
3355 int err;
3356
3357 BT_DBG("");
3358
Johan Hedberg28424702012-02-02 04:02:29 +02003359 hci_dev_lock(hdev);
3360
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003361 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003362 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3363 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003364 goto unlock;
3365 }
3366
Johan Hedberg28424702012-02-02 04:02:29 +02003367 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3368 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003369 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3370 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003371 goto unlock;
3372 }
3373
3374 conn = cmd->user_data;
3375
3376 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003377 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3378 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003379 goto unlock;
3380 }
3381
Johan Hedberga511b352014-12-11 21:45:45 +02003382 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3383 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003385 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3386 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003387unlock:
3388 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003389 return err;
3390}
3391
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003392static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003393 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003394 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003395{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003396 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003397 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003398 int err;
3399
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003400 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003401
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003402 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003403 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3404 MGMT_STATUS_NOT_POWERED, addr,
3405 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003406 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003407 }
3408
Johan Hedberg1707c602013-03-15 17:07:15 -05003409 if (addr->type == BDADDR_BREDR)
3410 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003411 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003412 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003413
Johan Hedberg272d90d2012-02-09 15:26:12 +02003414 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003415 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3416 MGMT_STATUS_NOT_CONNECTED, addr,
3417 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003418 goto done;
3419 }
3420
Johan Hedberg1707c602013-03-15 17:07:15 -05003421 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003422 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003423 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003424 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3425 MGMT_STATUS_SUCCESS, addr,
3426 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003427 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003428 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3429 MGMT_STATUS_FAILED, addr,
3430 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003431
Brian Gix47c15e22011-11-16 13:53:14 -08003432 goto done;
3433 }
3434
Johan Hedberg1707c602013-03-15 17:07:15 -05003435 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003436 if (!cmd) {
3437 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003438 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003439 }
3440
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003441 cmd->cmd_complete = addr_cmd_complete;
3442
Brian Gix0df4c182011-11-16 13:53:13 -08003443 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003444 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3445 struct hci_cp_user_passkey_reply cp;
3446
Johan Hedberg1707c602013-03-15 17:07:15 -05003447 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003448 cp.passkey = passkey;
3449 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3450 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003451 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3452 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003453
Johan Hedberga664b5b2011-02-19 12:06:02 -03003454 if (err < 0)
3455 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003456
Brian Gix0df4c182011-11-16 13:53:13 -08003457done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003458 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003459 return err;
3460}
3461
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303462static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3463 void *data, u16 len)
3464{
3465 struct mgmt_cp_pin_code_neg_reply *cp = data;
3466
3467 BT_DBG("");
3468
Johan Hedberg1707c602013-03-15 17:07:15 -05003469 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303470 MGMT_OP_PIN_CODE_NEG_REPLY,
3471 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3472}
3473
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003474static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3475 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003477 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003478
3479 BT_DBG("");
3480
3481 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003482 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3483 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003484
Johan Hedberg1707c602013-03-15 17:07:15 -05003485 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003486 MGMT_OP_USER_CONFIRM_REPLY,
3487 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003488}
3489
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003490static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003491 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003492{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003493 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003494
3495 BT_DBG("");
3496
Johan Hedberg1707c602013-03-15 17:07:15 -05003497 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003498 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3499 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003500}
3501
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3503 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003504{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003505 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003506
3507 BT_DBG("");
3508
Johan Hedberg1707c602013-03-15 17:07:15 -05003509 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003510 MGMT_OP_USER_PASSKEY_REPLY,
3511 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003512}
3513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003515 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003516{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003517 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003518
3519 BT_DBG("");
3520
Johan Hedberg1707c602013-03-15 17:07:15 -05003521 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003522 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3523 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003524}
3525
Johan Hedberg13928972013-03-15 17:07:00 -05003526static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003527{
Johan Hedberg13928972013-03-15 17:07:00 -05003528 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003529 struct hci_cp_write_local_name cp;
3530
Johan Hedberg13928972013-03-15 17:07:00 -05003531 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003532
Johan Hedberg890ea892013-03-15 17:06:52 -05003533 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003534}
3535
Marcel Holtmann1904a852015-01-11 13:50:44 -08003536static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003537{
3538 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003539 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003540
3541 BT_DBG("status 0x%02x", status);
3542
3543 hci_dev_lock(hdev);
3544
3545 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3546 if (!cmd)
3547 goto unlock;
3548
3549 cp = cmd->param;
3550
3551 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003552 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3553 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003554 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003555 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3556 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003557
3558 mgmt_pending_remove(cmd);
3559
3560unlock:
3561 hci_dev_unlock(hdev);
3562}
3563
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003564static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003565 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003566{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003567 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003568 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003569 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003570 int err;
3571
3572 BT_DBG("");
3573
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003574 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003575
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003576 /* If the old values are the same as the new ones just return a
3577 * direct command complete event.
3578 */
3579 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3580 !memcmp(hdev->short_name, cp->short_name,
3581 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003582 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3583 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003584 goto failed;
3585 }
3586
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003587 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003588
Johan Hedbergb5235a62012-02-21 14:32:24 +02003589 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003590 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003591
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003592 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3593 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003594 if (err < 0)
3595 goto failed;
3596
3597 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003598 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003599
Johan Hedbergb5235a62012-02-21 14:32:24 +02003600 goto failed;
3601 }
3602
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003603 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003604 if (!cmd) {
3605 err = -ENOMEM;
3606 goto failed;
3607 }
3608
Johan Hedberg13928972013-03-15 17:07:00 -05003609 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3610
Johan Hedberg890ea892013-03-15 17:06:52 -05003611 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003612
3613 if (lmp_bredr_capable(hdev)) {
3614 update_name(&req);
3615 update_eir(&req);
3616 }
3617
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003618 /* The name is stored in the scan response data and so
3619 * no need to udpate the advertising data here.
3620 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003621 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003622 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003623
Johan Hedberg13928972013-03-15 17:07:00 -05003624 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003625 if (err < 0)
3626 mgmt_pending_remove(cmd);
3627
3628failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003629 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003630 return err;
3631}
3632
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003633static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003634 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003635{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003636 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003637 int err;
3638
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003639 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003640
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003641 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003642
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003643 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003644 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3645 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003646 goto unlock;
3647 }
3648
Andre Guedes9a1a1992012-07-24 15:03:48 -03003649 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003650 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3651 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003652 goto unlock;
3653 }
3654
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003655 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003656 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3657 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003658 goto unlock;
3659 }
3660
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003661 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003662 if (!cmd) {
3663 err = -ENOMEM;
3664 goto unlock;
3665 }
3666
Johan Hedberg710f11c2014-05-26 11:21:22 +03003667 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003668 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3669 0, NULL);
3670 else
3671 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3672
Szymon Jancc35938b2011-03-22 13:12:21 +01003673 if (err < 0)
3674 mgmt_pending_remove(cmd);
3675
3676unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003677 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003678 return err;
3679}
3680
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003681static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003682 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003683{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003684 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003685 int err;
3686
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003687 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003688
Johan Hedberg5d57e792015-01-23 10:10:38 +02003689 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003690 return mgmt_cmd_complete(sk, hdev->id,
3691 MGMT_OP_ADD_REMOTE_OOB_DATA,
3692 MGMT_STATUS_INVALID_PARAMS,
3693 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003694
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003695 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003696
Marcel Holtmannec109112014-01-10 02:07:30 -08003697 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3698 struct mgmt_cp_add_remote_oob_data *cp = data;
3699 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003700
Johan Hedbergc19a4952014-11-17 20:52:19 +02003701 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003702 err = mgmt_cmd_complete(sk, hdev->id,
3703 MGMT_OP_ADD_REMOTE_OOB_DATA,
3704 MGMT_STATUS_INVALID_PARAMS,
3705 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003706 goto unlock;
3707 }
3708
Marcel Holtmannec109112014-01-10 02:07:30 -08003709 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003710 cp->addr.type, cp->hash,
3711 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003712 if (err < 0)
3713 status = MGMT_STATUS_FAILED;
3714 else
3715 status = MGMT_STATUS_SUCCESS;
3716
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003717 err = mgmt_cmd_complete(sk, hdev->id,
3718 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3719 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003720 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3721 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003722 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003723 u8 status;
3724
Johan Hedberg86df9202014-10-26 20:52:27 +01003725 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003726 /* Enforce zero-valued 192-bit parameters as
3727 * long as legacy SMP OOB isn't implemented.
3728 */
3729 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3730 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003731 err = mgmt_cmd_complete(sk, hdev->id,
3732 MGMT_OP_ADD_REMOTE_OOB_DATA,
3733 MGMT_STATUS_INVALID_PARAMS,
3734 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003735 goto unlock;
3736 }
3737
Johan Hedberg86df9202014-10-26 20:52:27 +01003738 rand192 = NULL;
3739 hash192 = NULL;
3740 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003741 /* In case one of the P-192 values is set to zero,
3742 * then just disable OOB data for P-192.
3743 */
3744 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3745 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3746 rand192 = NULL;
3747 hash192 = NULL;
3748 } else {
3749 rand192 = cp->rand192;
3750 hash192 = cp->hash192;
3751 }
3752 }
3753
3754 /* In case one of the P-256 values is set to zero, then just
3755 * disable OOB data for P-256.
3756 */
3757 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3758 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3759 rand256 = NULL;
3760 hash256 = NULL;
3761 } else {
3762 rand256 = cp->rand256;
3763 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003764 }
3765
Johan Hedberg81328d52014-10-26 20:33:47 +01003766 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003767 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003768 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003769 if (err < 0)
3770 status = MGMT_STATUS_FAILED;
3771 else
3772 status = MGMT_STATUS_SUCCESS;
3773
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003774 err = mgmt_cmd_complete(sk, hdev->id,
3775 MGMT_OP_ADD_REMOTE_OOB_DATA,
3776 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003777 } else {
3778 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003779 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3780 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003781 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003782
Johan Hedbergc19a4952014-11-17 20:52:19 +02003783unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003784 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003785 return err;
3786}
3787
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003788static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003789 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003790{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003791 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003792 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003793 int err;
3794
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003795 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003796
Johan Hedbergc19a4952014-11-17 20:52:19 +02003797 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003798 return mgmt_cmd_complete(sk, hdev->id,
3799 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3800 MGMT_STATUS_INVALID_PARAMS,
3801 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003802
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003803 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003804
Johan Hedbergeedbd582014-11-15 09:34:23 +02003805 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3806 hci_remote_oob_data_clear(hdev);
3807 status = MGMT_STATUS_SUCCESS;
3808 goto done;
3809 }
3810
Johan Hedberg6928a922014-10-26 20:46:09 +01003811 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003812 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003813 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003814 else
Szymon Janca6785be2012-12-13 15:11:21 +01003815 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003816
Johan Hedbergeedbd582014-11-15 09:34:23 +02003817done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003818 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3819 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003820
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003821 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003822 return err;
3823}
3824
Marcel Holtmann80190442014-12-04 11:36:36 +01003825static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003826{
Marcel Holtmann80190442014-12-04 11:36:36 +01003827 struct hci_dev *hdev = req->hdev;
3828 struct hci_cp_le_set_scan_param param_cp;
3829 struct hci_cp_le_set_scan_enable enable_cp;
3830 struct hci_cp_inquiry inq_cp;
3831 /* General inquiry access code (GIAC) */
3832 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3833 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003834 int err;
3835
Marcel Holtmann80190442014-12-04 11:36:36 +01003836 switch (hdev->discovery.type) {
3837 case DISCOV_TYPE_BREDR:
3838 *status = mgmt_bredr_support(hdev);
3839 if (*status)
3840 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003841
Marcel Holtmann80190442014-12-04 11:36:36 +01003842 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3843 *status = MGMT_STATUS_BUSY;
3844 return false;
3845 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003846
Marcel Holtmann80190442014-12-04 11:36:36 +01003847 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003848
Marcel Holtmann80190442014-12-04 11:36:36 +01003849 memset(&inq_cp, 0, sizeof(inq_cp));
3850 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3851 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3852 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3853 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003854
Marcel Holtmann80190442014-12-04 11:36:36 +01003855 case DISCOV_TYPE_LE:
3856 case DISCOV_TYPE_INTERLEAVED:
3857 *status = mgmt_le_support(hdev);
3858 if (*status)
3859 return false;
3860
3861 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003862 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003863 *status = MGMT_STATUS_NOT_SUPPORTED;
3864 return false;
3865 }
3866
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003867 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003868 /* Don't let discovery abort an outgoing
3869 * connection attempt that's using directed
3870 * advertising.
3871 */
3872 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3873 BT_CONNECT)) {
3874 *status = MGMT_STATUS_REJECTED;
3875 return false;
3876 }
3877
3878 disable_advertising(req);
3879 }
3880
3881 /* If controller is scanning, it means the background scanning
3882 * is running. Thus, we should temporarily stop it in order to
3883 * set the discovery scanning parameters.
3884 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003885 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
Marcel Holtmann80190442014-12-04 11:36:36 +01003886 hci_req_add_le_scan_disable(req);
3887
3888 memset(&param_cp, 0, sizeof(param_cp));
3889
3890 /* All active scans will be done with either a resolvable
3891 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003892 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003893 */
3894 err = hci_update_random_address(req, true, &own_addr_type);
3895 if (err < 0) {
3896 *status = MGMT_STATUS_FAILED;
3897 return false;
3898 }
3899
3900 param_cp.type = LE_SCAN_ACTIVE;
3901 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3902 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3903 param_cp.own_address_type = own_addr_type;
3904 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3905 &param_cp);
3906
3907 memset(&enable_cp, 0, sizeof(enable_cp));
3908 enable_cp.enable = LE_SCAN_ENABLE;
3909 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3910 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3911 &enable_cp);
3912 break;
3913
3914 default:
3915 *status = MGMT_STATUS_INVALID_PARAMS;
3916 return false;
3917 }
3918
3919 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003920}
3921
Marcel Holtmann1904a852015-01-11 13:50:44 -08003922static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3923 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003924{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003925 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003926 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003927
Andre Guedes7c307722013-04-30 15:29:28 -03003928 BT_DBG("status %d", status);
3929
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003930 hci_dev_lock(hdev);
3931
3932 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003933 if (!cmd)
3934 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3935
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003936 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003937 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003938 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003939 }
3940
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003941 if (status) {
3942 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3943 goto unlock;
3944 }
3945
Andre Guedes7c307722013-04-30 15:29:28 -03003946 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003947
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003948 /* If the scan involves LE scan, pick proper timeout to schedule
3949 * hdev->le_scan_disable that will stop it.
3950 */
Andre Guedes7c307722013-04-30 15:29:28 -03003951 switch (hdev->discovery.type) {
3952 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003953 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003954 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003955 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003956 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003957 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003958 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003959 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003960 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003961 default:
3962 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003963 timeout = 0;
3964 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003965 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003966
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003967 if (timeout) {
3968 /* When service discovery is used and the controller has
3969 * a strict duplicate filter, it is important to remember
3970 * the start and duration of the scan. This is required
3971 * for restarting scanning during the discovery phase.
3972 */
3973 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3974 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003975 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003976 hdev->discovery.scan_start = jiffies;
3977 hdev->discovery.scan_duration = timeout;
3978 }
3979
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003980 queue_delayed_work(hdev->workqueue,
3981 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003982 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003983
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003984unlock:
3985 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003986}
3987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003988static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003989 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003990{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003991 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003992 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003993 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003994 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003995 int err;
3996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003997 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003998
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003999 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004000
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004001 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004002 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4003 MGMT_STATUS_NOT_POWERED,
4004 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004005 goto failed;
4006 }
4007
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004008 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004009 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004010 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4011 MGMT_STATUS_BUSY, &cp->type,
4012 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004013 goto failed;
4014 }
4015
Johan Hedberg2922a942014-12-05 13:36:06 +02004016 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004017 if (!cmd) {
4018 err = -ENOMEM;
4019 goto failed;
4020 }
4021
Johan Hedberg2922a942014-12-05 13:36:06 +02004022 cmd->cmd_complete = generic_cmd_complete;
4023
Marcel Holtmann22078802014-12-05 11:45:22 +01004024 /* Clear the discovery filter first to free any previously
4025 * allocated memory for the UUID list.
4026 */
4027 hci_discovery_filter_clear(hdev);
4028
Andre Guedes4aab14e2012-02-17 20:39:36 -03004029 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004030 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004031
Andre Guedes7c307722013-04-30 15:29:28 -03004032 hci_req_init(&req, hdev);
4033
Marcel Holtmann80190442014-12-04 11:36:36 +01004034 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004035 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4036 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004037 mgmt_pending_remove(cmd);
4038 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004039 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004040
Andre Guedes7c307722013-04-30 15:29:28 -03004041 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004042 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004043 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004044 goto failed;
4045 }
4046
4047 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004048
4049failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004050 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004051 return err;
4052}
4053
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004054static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4055 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004056{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004057 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4058 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004059}
4060
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004061static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4062 void *data, u16 len)
4063{
4064 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004065 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004066 struct hci_request req;
4067 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4068 u16 uuid_count, expected_len;
4069 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004070 int err;
4071
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004072 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004073
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004074 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004075
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004076 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004077 err = mgmt_cmd_complete(sk, hdev->id,
4078 MGMT_OP_START_SERVICE_DISCOVERY,
4079 MGMT_STATUS_NOT_POWERED,
4080 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004081 goto failed;
4082 }
4083
4084 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004085 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004086 err = mgmt_cmd_complete(sk, hdev->id,
4087 MGMT_OP_START_SERVICE_DISCOVERY,
4088 MGMT_STATUS_BUSY, &cp->type,
4089 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004090 goto failed;
4091 }
4092
4093 uuid_count = __le16_to_cpu(cp->uuid_count);
4094 if (uuid_count > max_uuid_count) {
4095 BT_ERR("service_discovery: too big uuid_count value %u",
4096 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004097 err = mgmt_cmd_complete(sk, hdev->id,
4098 MGMT_OP_START_SERVICE_DISCOVERY,
4099 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4100 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004101 goto failed;
4102 }
4103
4104 expected_len = sizeof(*cp) + uuid_count * 16;
4105 if (expected_len != len) {
4106 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4107 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004108 err = mgmt_cmd_complete(sk, hdev->id,
4109 MGMT_OP_START_SERVICE_DISCOVERY,
4110 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4111 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004112 goto failed;
4113 }
4114
4115 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004116 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004117 if (!cmd) {
4118 err = -ENOMEM;
4119 goto failed;
4120 }
4121
Johan Hedberg2922a942014-12-05 13:36:06 +02004122 cmd->cmd_complete = service_discovery_cmd_complete;
4123
Marcel Holtmann22078802014-12-05 11:45:22 +01004124 /* Clear the discovery filter first to free any previously
4125 * allocated memory for the UUID list.
4126 */
4127 hci_discovery_filter_clear(hdev);
4128
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004129 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004130 hdev->discovery.type = cp->type;
4131 hdev->discovery.rssi = cp->rssi;
4132 hdev->discovery.uuid_count = uuid_count;
4133
4134 if (uuid_count > 0) {
4135 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4136 GFP_KERNEL);
4137 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004138 err = mgmt_cmd_complete(sk, hdev->id,
4139 MGMT_OP_START_SERVICE_DISCOVERY,
4140 MGMT_STATUS_FAILED,
4141 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004142 mgmt_pending_remove(cmd);
4143 goto failed;
4144 }
4145 }
4146
4147 hci_req_init(&req, hdev);
4148
4149 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004150 err = mgmt_cmd_complete(sk, hdev->id,
4151 MGMT_OP_START_SERVICE_DISCOVERY,
4152 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004153 mgmt_pending_remove(cmd);
4154 goto failed;
4155 }
4156
4157 err = hci_req_run(&req, start_discovery_complete);
4158 if (err < 0) {
4159 mgmt_pending_remove(cmd);
4160 goto failed;
4161 }
4162
4163 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4164
4165failed:
4166 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004167 return err;
4168}
4169
Marcel Holtmann1904a852015-01-11 13:50:44 -08004170static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004171{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004172 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004173
Andre Guedes0e05bba2013-04-30 15:29:33 -03004174 BT_DBG("status %d", status);
4175
4176 hci_dev_lock(hdev);
4177
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004178 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4179 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004180 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004181 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004182 }
4183
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004184 if (!status)
4185 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004186
Andre Guedes0e05bba2013-04-30 15:29:33 -03004187 hci_dev_unlock(hdev);
4188}
4189
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004190static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004191 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004192{
Johan Hedbergd9306502012-02-20 23:25:18 +02004193 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004194 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004195 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004196 int err;
4197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004198 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004199
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004200 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004201
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004202 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004203 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4204 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4205 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004206 goto unlock;
4207 }
4208
4209 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004210 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4211 MGMT_STATUS_INVALID_PARAMS,
4212 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004213 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004214 }
4215
Johan Hedberg2922a942014-12-05 13:36:06 +02004216 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004217 if (!cmd) {
4218 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004219 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004220 }
4221
Johan Hedberg2922a942014-12-05 13:36:06 +02004222 cmd->cmd_complete = generic_cmd_complete;
4223
Andre Guedes0e05bba2013-04-30 15:29:33 -03004224 hci_req_init(&req, hdev);
4225
Johan Hedberg21a60d32014-06-10 14:05:58 +03004226 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004227
Johan Hedberg21a60d32014-06-10 14:05:58 +03004228 err = hci_req_run(&req, stop_discovery_complete);
4229 if (!err) {
4230 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004231 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004232 }
4233
Johan Hedberg21a60d32014-06-10 14:05:58 +03004234 mgmt_pending_remove(cmd);
4235
4236 /* If no HCI commands were sent we're done */
4237 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004238 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4239 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004240 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4241 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004242
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004243unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004244 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004245 return err;
4246}
4247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004248static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004249 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004250{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004251 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004252 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004253 int err;
4254
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004255 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004256
Johan Hedberg561aafb2012-01-04 13:31:59 +02004257 hci_dev_lock(hdev);
4258
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004259 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004260 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4261 MGMT_STATUS_FAILED, &cp->addr,
4262 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004263 goto failed;
4264 }
4265
Johan Hedberga198e7b2012-02-17 14:27:06 +02004266 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004267 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004268 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4269 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4270 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004271 goto failed;
4272 }
4273
4274 if (cp->name_known) {
4275 e->name_state = NAME_KNOWN;
4276 list_del(&e->list);
4277 } else {
4278 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004279 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004280 }
4281
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004282 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4283 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004284
4285failed:
4286 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004287 return err;
4288}
4289
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004290static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004291 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004292{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004293 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004294 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004295 int err;
4296
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004297 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004298
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004299 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004300 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4301 MGMT_STATUS_INVALID_PARAMS,
4302 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004303
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004304 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004305
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004306 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4307 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004308 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004309 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004310 goto done;
4311 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004312
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004313 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4314 sk);
4315 status = MGMT_STATUS_SUCCESS;
4316
4317done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004318 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4319 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004320
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004321 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004322
4323 return err;
4324}
4325
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004326static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004327 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004328{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004329 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004330 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004331 int err;
4332
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004333 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004334
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004335 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004336 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4337 MGMT_STATUS_INVALID_PARAMS,
4338 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004339
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004340 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004341
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004342 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4343 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004344 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004345 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004346 goto done;
4347 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004348
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004349 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4350 sk);
4351 status = MGMT_STATUS_SUCCESS;
4352
4353done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004354 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4355 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004356
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004357 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004358
4359 return err;
4360}
4361
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004362static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4363 u16 len)
4364{
4365 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004366 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004367 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004368 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004369
4370 BT_DBG("%s", hdev->name);
4371
Szymon Jancc72d4b82012-03-16 16:02:57 +01004372 source = __le16_to_cpu(cp->source);
4373
4374 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004375 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4376 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004377
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004378 hci_dev_lock(hdev);
4379
Szymon Jancc72d4b82012-03-16 16:02:57 +01004380 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004381 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4382 hdev->devid_product = __le16_to_cpu(cp->product);
4383 hdev->devid_version = __le16_to_cpu(cp->version);
4384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004385 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4386 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004387
Johan Hedberg890ea892013-03-15 17:06:52 -05004388 hci_req_init(&req, hdev);
4389 update_eir(&req);
4390 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004391
4392 hci_dev_unlock(hdev);
4393
4394 return err;
4395}
4396
Marcel Holtmann1904a852015-01-11 13:50:44 -08004397static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4398 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004399{
4400 struct cmd_lookup match = { NULL, hdev };
4401
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304402 hci_dev_lock(hdev);
4403
Johan Hedberg4375f102013-09-25 13:26:10 +03004404 if (status) {
4405 u8 mgmt_err = mgmt_status(status);
4406
4407 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4408 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304409 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004410 }
4411
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004412 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004413 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004414 else
4415 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4416
Johan Hedberg4375f102013-09-25 13:26:10 +03004417 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4418 &match);
4419
4420 new_settings(hdev, match.sk);
4421
4422 if (match.sk)
4423 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304424
4425unlock:
4426 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004427}
4428
Marcel Holtmann21b51872013-10-10 09:47:53 -07004429static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4430 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004431{
4432 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004433 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004434 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004435 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004436 int err;
4437
4438 BT_DBG("request for %s", hdev->name);
4439
Johan Hedberge6fe7982013-10-02 15:45:22 +03004440 status = mgmt_le_support(hdev);
4441 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004442 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4443 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004444
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004445 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004446 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4447 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004448
4449 hci_dev_lock(hdev);
4450
4451 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004452
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004453 /* The following conditions are ones which mean that we should
4454 * not do any HCI communication but directly send a mgmt
4455 * response to user space (after toggling the flag if
4456 * necessary).
4457 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004458 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004459 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4460 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004461 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004462 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004463 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004464 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004465
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004466 if (cp->val) {
4467 changed = !test_and_set_bit(HCI_ADVERTISING,
4468 &hdev->dev_flags);
4469 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004470 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004471 else
4472 clear_bit(HCI_ADVERTISING_CONNECTABLE,
4473 &hdev->dev_flags);
4474 } else {
4475 changed = test_and_clear_bit(HCI_ADVERTISING,
4476 &hdev->dev_flags);
4477 clear_bit(HCI_ADVERTISING_CONNECTABLE,
4478 &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004479 }
4480
4481 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4482 if (err < 0)
4483 goto unlock;
4484
4485 if (changed)
4486 err = new_settings(hdev, sk);
4487
4488 goto unlock;
4489 }
4490
4491 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4492 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004493 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4494 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004495 goto unlock;
4496 }
4497
4498 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4499 if (!cmd) {
4500 err = -ENOMEM;
4501 goto unlock;
4502 }
4503
4504 hci_req_init(&req, hdev);
4505
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004506 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004507 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004508 else
4509 clear_bit(HCI_ADVERTISING_CONNECTABLE, &hdev->dev_flags);
4510
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004511 if (val)
4512 enable_advertising(&req);
4513 else
4514 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004515
4516 err = hci_req_run(&req, set_advertising_complete);
4517 if (err < 0)
4518 mgmt_pending_remove(cmd);
4519
4520unlock:
4521 hci_dev_unlock(hdev);
4522 return err;
4523}
4524
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004525static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4526 void *data, u16 len)
4527{
4528 struct mgmt_cp_set_static_address *cp = data;
4529 int err;
4530
4531 BT_DBG("%s", hdev->name);
4532
Marcel Holtmann62af4442013-10-02 22:10:32 -07004533 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004534 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4535 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004536
4537 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004538 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4539 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004540
4541 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4542 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004543 return mgmt_cmd_status(sk, hdev->id,
4544 MGMT_OP_SET_STATIC_ADDRESS,
4545 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004546
4547 /* Two most significant bits shall be set */
4548 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004549 return mgmt_cmd_status(sk, hdev->id,
4550 MGMT_OP_SET_STATIC_ADDRESS,
4551 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004552 }
4553
4554 hci_dev_lock(hdev);
4555
4556 bacpy(&hdev->static_addr, &cp->bdaddr);
4557
Marcel Holtmann93690c22015-03-06 10:11:21 -08004558 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4559 if (err < 0)
4560 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004561
Marcel Holtmann93690c22015-03-06 10:11:21 -08004562 err = new_settings(hdev, sk);
4563
4564unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004565 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004566 return err;
4567}
4568
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004569static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4570 void *data, u16 len)
4571{
4572 struct mgmt_cp_set_scan_params *cp = data;
4573 __u16 interval, window;
4574 int err;
4575
4576 BT_DBG("%s", hdev->name);
4577
4578 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004579 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4580 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004581
4582 interval = __le16_to_cpu(cp->interval);
4583
4584 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004585 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4586 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004587
4588 window = __le16_to_cpu(cp->window);
4589
4590 if (window < 0x0004 || window > 0x4000)
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 Holtmann14b49b92013-10-11 08:23:20 -07004593
Marcel Holtmann899e1072013-10-14 09:55:32 -07004594 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004595 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4596 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004597
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004598 hci_dev_lock(hdev);
4599
4600 hdev->le_scan_interval = interval;
4601 hdev->le_scan_window = window;
4602
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004603 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4604 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004605
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004606 /* If background scan is running, restart it so new parameters are
4607 * loaded.
4608 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004609 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004610 hdev->discovery.state == DISCOVERY_STOPPED) {
4611 struct hci_request req;
4612
4613 hci_req_init(&req, hdev);
4614
4615 hci_req_add_le_scan_disable(&req);
4616 hci_req_add_le_passive_scan(&req);
4617
4618 hci_req_run(&req, NULL);
4619 }
4620
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004621 hci_dev_unlock(hdev);
4622
4623 return err;
4624}
4625
Marcel Holtmann1904a852015-01-11 13:50:44 -08004626static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4627 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004628{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004629 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004630
4631 BT_DBG("status 0x%02x", status);
4632
4633 hci_dev_lock(hdev);
4634
4635 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4636 if (!cmd)
4637 goto unlock;
4638
4639 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004640 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4641 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004642 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004643 struct mgmt_mode *cp = cmd->param;
4644
4645 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004646 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004647 else
4648 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4649
Johan Hedberg33e38b32013-03-15 17:07:05 -05004650 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4651 new_settings(hdev, cmd->sk);
4652 }
4653
4654 mgmt_pending_remove(cmd);
4655
4656unlock:
4657 hci_dev_unlock(hdev);
4658}
4659
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004660static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004661 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004662{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004663 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004664 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004665 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004666 int err;
4667
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004668 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004670 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004671 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004672 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4673 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004674
Johan Hedberga7e80f22013-01-09 16:05:19 +02004675 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004676 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4677 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004678
Antti Julkuf6422ec2011-06-22 13:11:56 +03004679 hci_dev_lock(hdev);
4680
Johan Hedberg05cbf292013-03-15 17:07:07 -05004681 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004682 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4683 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004684 goto unlock;
4685 }
4686
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004687 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004688 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4689 hdev);
4690 goto unlock;
4691 }
4692
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004693 if (!hdev_is_powered(hdev)) {
4694 change_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4695 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4696 hdev);
4697 new_settings(hdev, sk);
4698 goto unlock;
4699 }
4700
Johan Hedberg33e38b32013-03-15 17:07:05 -05004701 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4702 data, len);
4703 if (!cmd) {
4704 err = -ENOMEM;
4705 goto unlock;
4706 }
4707
4708 hci_req_init(&req, hdev);
4709
Johan Hedberg406d7802013-03-15 17:07:09 -05004710 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004711
4712 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004713 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004714 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4715 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004716 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004717 }
4718
Johan Hedberg33e38b32013-03-15 17:07:05 -05004719unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004720 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004721
Antti Julkuf6422ec2011-06-22 13:11:56 +03004722 return err;
4723}
4724
Marcel Holtmann1904a852015-01-11 13:50:44 -08004725static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004726{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004727 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004728
4729 BT_DBG("status 0x%02x", status);
4730
4731 hci_dev_lock(hdev);
4732
4733 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4734 if (!cmd)
4735 goto unlock;
4736
4737 if (status) {
4738 u8 mgmt_err = mgmt_status(status);
4739
4740 /* We need to restore the flag if related HCI commands
4741 * failed.
4742 */
4743 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4744
Johan Hedberga69e8372015-03-06 21:08:53 +02004745 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004746 } else {
4747 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4748 new_settings(hdev, cmd->sk);
4749 }
4750
4751 mgmt_pending_remove(cmd);
4752
4753unlock:
4754 hci_dev_unlock(hdev);
4755}
4756
4757static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4758{
4759 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004760 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004761 struct hci_request req;
4762 int err;
4763
4764 BT_DBG("request for %s", hdev->name);
4765
4766 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004767 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4768 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004769
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004770 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004771 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4772 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004773
4774 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004775 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4776 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004777
4778 hci_dev_lock(hdev);
4779
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004780 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004781 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4782 goto unlock;
4783 }
4784
4785 if (!hdev_is_powered(hdev)) {
4786 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004787 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4788 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4789 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4790 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4791 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4792 }
4793
4794 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4795
4796 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4797 if (err < 0)
4798 goto unlock;
4799
4800 err = new_settings(hdev, sk);
4801 goto unlock;
4802 }
4803
4804 /* Reject disabling when powered on */
4805 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004806 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4807 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004808 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004809 } else {
4810 /* When configuring a dual-mode controller to operate
4811 * with LE only and using a static address, then switching
4812 * BR/EDR back on is not allowed.
4813 *
4814 * Dual-mode controllers shall operate with the public
4815 * address as its identity address for BR/EDR and LE. So
4816 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004817 *
4818 * The same restrictions applies when secure connections
4819 * has been enabled. For BR/EDR this is a controller feature
4820 * while for LE it is a host stack feature. This means that
4821 * switching BR/EDR back on when secure connections has been
4822 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004823 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004824 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004825 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004826 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004827 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4828 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004829 goto unlock;
4830 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004831 }
4832
4833 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004834 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4835 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004836 goto unlock;
4837 }
4838
4839 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4840 if (!cmd) {
4841 err = -ENOMEM;
4842 goto unlock;
4843 }
4844
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004845 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004846 * generates the correct flags.
4847 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004848 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004849
4850 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004851
Johan Hedberg432df052014-08-01 11:13:31 +03004852 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004853 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004854
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004855 /* Since only the advertising data flags will change, there
4856 * is no need to update the scan response data.
4857 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004858 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004859
Johan Hedberg0663ca22013-10-02 13:43:14 +03004860 err = hci_req_run(&req, set_bredr_complete);
4861 if (err < 0)
4862 mgmt_pending_remove(cmd);
4863
4864unlock:
4865 hci_dev_unlock(hdev);
4866 return err;
4867}
4868
Johan Hedberga1443f52015-01-23 15:42:46 +02004869static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4870{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004871 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004872 struct mgmt_mode *cp;
4873
4874 BT_DBG("%s status %u", hdev->name, status);
4875
4876 hci_dev_lock(hdev);
4877
4878 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4879 if (!cmd)
4880 goto unlock;
4881
4882 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004883 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4884 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004885 goto remove;
4886 }
4887
4888 cp = cmd->param;
4889
4890 switch (cp->val) {
4891 case 0x00:
4892 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4893 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4894 break;
4895 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004896 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Johan Hedberga1443f52015-01-23 15:42:46 +02004897 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4898 break;
4899 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004900 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
4901 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004902 break;
4903 }
4904
4905 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4906 new_settings(hdev, cmd->sk);
4907
4908remove:
4909 mgmt_pending_remove(cmd);
4910unlock:
4911 hci_dev_unlock(hdev);
4912}
4913
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004914static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4915 void *data, u16 len)
4916{
4917 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004918 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004919 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004920 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004921 int err;
4922
4923 BT_DBG("request for %s", hdev->name);
4924
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004925 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004926 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004927 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4928 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004929
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004930 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004931 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004932 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004933 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4934 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004935
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004936 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004937 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004938 MGMT_STATUS_INVALID_PARAMS);
4939
4940 hci_dev_lock(hdev);
4941
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004942 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004943 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004944 bool changed;
4945
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004946 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004947 changed = !test_and_set_bit(HCI_SC_ENABLED,
4948 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004949 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004950 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004951 else
4952 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4953 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004954 changed = test_and_clear_bit(HCI_SC_ENABLED,
4955 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004956 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4957 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004958
4959 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4960 if (err < 0)
4961 goto failed;
4962
4963 if (changed)
4964 err = new_settings(hdev, sk);
4965
4966 goto failed;
4967 }
4968
4969 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004970 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4971 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004972 goto failed;
4973 }
4974
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004975 val = !!cp->val;
4976
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004977 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
4978 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004979 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4980 goto failed;
4981 }
4982
4983 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4984 if (!cmd) {
4985 err = -ENOMEM;
4986 goto failed;
4987 }
4988
Johan Hedberga1443f52015-01-23 15:42:46 +02004989 hci_req_init(&req, hdev);
4990 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4991 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004992 if (err < 0) {
4993 mgmt_pending_remove(cmd);
4994 goto failed;
4995 }
4996
4997failed:
4998 hci_dev_unlock(hdev);
4999 return err;
5000}
5001
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005002static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5003 void *data, u16 len)
5004{
5005 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005006 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005007 int err;
5008
5009 BT_DBG("request for %s", hdev->name);
5010
Johan Hedbergb97109792014-06-24 14:00:28 +03005011 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005012 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5013 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005014
5015 hci_dev_lock(hdev);
5016
5017 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03005018 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
5019 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005020 else
Johan Hedberg0663b292014-06-24 13:15:50 +03005021 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
5022 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005023
Johan Hedbergb97109792014-06-24 14:00:28 +03005024 if (cp->val == 0x02)
5025 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
5026 &hdev->dev_flags);
5027 else
5028 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
5029 &hdev->dev_flags);
5030
5031 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005032 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005033 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5034 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5035 sizeof(mode), &mode);
5036 }
5037
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005038 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5039 if (err < 0)
5040 goto unlock;
5041
5042 if (changed)
5043 err = new_settings(hdev, sk);
5044
5045unlock:
5046 hci_dev_unlock(hdev);
5047 return err;
5048}
5049
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005050static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5051 u16 len)
5052{
5053 struct mgmt_cp_set_privacy *cp = cp_data;
5054 bool changed;
5055 int err;
5056
5057 BT_DBG("request for %s", hdev->name);
5058
5059 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005060 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5061 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005062
5063 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005064 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5065 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005066
5067 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005068 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5069 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005070
5071 hci_dev_lock(hdev);
5072
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005073 /* If user space supports this command it is also expected to
5074 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5075 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005076 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005077
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005078 if (cp->privacy) {
5079 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5080 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005081 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005082 } else {
5083 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5084 memset(hdev->irk, 0, sizeof(hdev->irk));
5085 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5086 }
5087
5088 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5089 if (err < 0)
5090 goto unlock;
5091
5092 if (changed)
5093 err = new_settings(hdev, sk);
5094
5095unlock:
5096 hci_dev_unlock(hdev);
5097 return err;
5098}
5099
Johan Hedberg41edf162014-02-18 10:19:35 +02005100static bool irk_is_valid(struct mgmt_irk_info *irk)
5101{
5102 switch (irk->addr.type) {
5103 case BDADDR_LE_PUBLIC:
5104 return true;
5105
5106 case BDADDR_LE_RANDOM:
5107 /* Two most significant bits shall be set */
5108 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5109 return false;
5110 return true;
5111 }
5112
5113 return false;
5114}
5115
5116static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5117 u16 len)
5118{
5119 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005120 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5121 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005122 u16 irk_count, expected_len;
5123 int i, err;
5124
5125 BT_DBG("request for %s", hdev->name);
5126
5127 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005128 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5129 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005130
5131 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005132 if (irk_count > max_irk_count) {
5133 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005134 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5135 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005136 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005137
5138 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5139 if (expected_len != len) {
5140 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005141 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005142 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5143 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005144 }
5145
5146 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5147
5148 for (i = 0; i < irk_count; i++) {
5149 struct mgmt_irk_info *key = &cp->irks[i];
5150
5151 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005152 return mgmt_cmd_status(sk, hdev->id,
5153 MGMT_OP_LOAD_IRKS,
5154 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005155 }
5156
5157 hci_dev_lock(hdev);
5158
5159 hci_smp_irks_clear(hdev);
5160
5161 for (i = 0; i < irk_count; i++) {
5162 struct mgmt_irk_info *irk = &cp->irks[i];
5163 u8 addr_type;
5164
5165 if (irk->addr.type == BDADDR_LE_PUBLIC)
5166 addr_type = ADDR_LE_DEV_PUBLIC;
5167 else
5168 addr_type = ADDR_LE_DEV_RANDOM;
5169
5170 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5171 BDADDR_ANY);
5172 }
5173
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005174 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005175
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005176 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005177
5178 hci_dev_unlock(hdev);
5179
5180 return err;
5181}
5182
Johan Hedberg3f706b72013-01-20 14:27:16 +02005183static bool ltk_is_valid(struct mgmt_ltk_info *key)
5184{
5185 if (key->master != 0x00 && key->master != 0x01)
5186 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005187
5188 switch (key->addr.type) {
5189 case BDADDR_LE_PUBLIC:
5190 return true;
5191
5192 case BDADDR_LE_RANDOM:
5193 /* Two most significant bits shall be set */
5194 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5195 return false;
5196 return true;
5197 }
5198
5199 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005200}
5201
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005202static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005203 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005204{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005205 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005206 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5207 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005208 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005209 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005210
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005211 BT_DBG("request for %s", hdev->name);
5212
5213 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005214 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5215 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005216
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005217 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005218 if (key_count > max_key_count) {
5219 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005220 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5221 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005222 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005223
5224 expected_len = sizeof(*cp) + key_count *
5225 sizeof(struct mgmt_ltk_info);
5226 if (expected_len != len) {
5227 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005228 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005229 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5230 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005231 }
5232
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005233 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005234
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005235 for (i = 0; i < key_count; i++) {
5236 struct mgmt_ltk_info *key = &cp->keys[i];
5237
Johan Hedberg3f706b72013-01-20 14:27:16 +02005238 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005239 return mgmt_cmd_status(sk, hdev->id,
5240 MGMT_OP_LOAD_LONG_TERM_KEYS,
5241 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005242 }
5243
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005244 hci_dev_lock(hdev);
5245
5246 hci_smp_ltks_clear(hdev);
5247
5248 for (i = 0; i < key_count; i++) {
5249 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005250 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005251
5252 if (key->addr.type == BDADDR_LE_PUBLIC)
5253 addr_type = ADDR_LE_DEV_PUBLIC;
5254 else
5255 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005256
Johan Hedberg61b43352014-05-29 19:36:53 +03005257 switch (key->type) {
5258 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005259 authenticated = 0x00;
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;
5262 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005263 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005264 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005265 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005266 case MGMT_LTK_P256_UNAUTH:
5267 authenticated = 0x00;
5268 type = SMP_LTK_P256;
5269 break;
5270 case MGMT_LTK_P256_AUTH:
5271 authenticated = 0x01;
5272 type = SMP_LTK_P256;
5273 break;
5274 case MGMT_LTK_P256_DEBUG:
5275 authenticated = 0x00;
5276 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005277 default:
5278 continue;
5279 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005280
Johan Hedberg35d70272014-02-19 14:57:47 +02005281 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005282 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005283 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005284 }
5285
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005286 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005287 NULL, 0);
5288
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005289 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005290
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005291 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005292}
5293
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005294static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005295{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005296 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005297 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005298 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005299
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005300 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005301
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005302 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005303 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005304 rp.tx_power = conn->tx_power;
5305 rp.max_tx_power = conn->max_tx_power;
5306 } else {
5307 rp.rssi = HCI_RSSI_INVALID;
5308 rp.tx_power = HCI_TX_POWER_INVALID;
5309 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005310 }
5311
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005312 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5313 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005314
5315 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005316 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005317
5318 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005319}
5320
Marcel Holtmann1904a852015-01-11 13:50:44 -08005321static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5322 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005323{
5324 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005325 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005326 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005327 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005328 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005329
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005330 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005331
5332 hci_dev_lock(hdev);
5333
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005334 /* Commands sent in request are either Read RSSI or Read Transmit Power
5335 * Level so we check which one was last sent to retrieve connection
5336 * handle. Both commands have handle as first parameter so it's safe to
5337 * cast data on the same command struct.
5338 *
5339 * First command sent is always Read RSSI and we fail only if it fails.
5340 * In other case we simply override error to indicate success as we
5341 * already remembered if TX power value is actually valid.
5342 */
5343 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5344 if (!cp) {
5345 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005346 status = MGMT_STATUS_SUCCESS;
5347 } else {
5348 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005349 }
5350
5351 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005352 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005353 goto unlock;
5354 }
5355
5356 handle = __le16_to_cpu(cp->handle);
5357 conn = hci_conn_hash_lookup_handle(hdev, handle);
5358 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005359 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005360 goto unlock;
5361 }
5362
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005363 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5364 if (!cmd)
5365 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005366
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005367 cmd->cmd_complete(cmd, status);
5368 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005369
5370unlock:
5371 hci_dev_unlock(hdev);
5372}
5373
5374static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5375 u16 len)
5376{
5377 struct mgmt_cp_get_conn_info *cp = data;
5378 struct mgmt_rp_get_conn_info rp;
5379 struct hci_conn *conn;
5380 unsigned long conn_info_age;
5381 int err = 0;
5382
5383 BT_DBG("%s", hdev->name);
5384
5385 memset(&rp, 0, sizeof(rp));
5386 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5387 rp.addr.type = cp->addr.type;
5388
5389 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005390 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5391 MGMT_STATUS_INVALID_PARAMS,
5392 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005393
5394 hci_dev_lock(hdev);
5395
5396 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005397 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5398 MGMT_STATUS_NOT_POWERED, &rp,
5399 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005400 goto unlock;
5401 }
5402
5403 if (cp->addr.type == BDADDR_BREDR)
5404 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5405 &cp->addr.bdaddr);
5406 else
5407 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5408
5409 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005410 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5411 MGMT_STATUS_NOT_CONNECTED, &rp,
5412 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005413 goto unlock;
5414 }
5415
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005416 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005417 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5418 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005419 goto unlock;
5420 }
5421
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005422 /* To avoid client trying to guess when to poll again for information we
5423 * calculate conn info age as random value between min/max set in hdev.
5424 */
5425 conn_info_age = hdev->conn_info_min_age +
5426 prandom_u32_max(hdev->conn_info_max_age -
5427 hdev->conn_info_min_age);
5428
5429 /* Query controller to refresh cached values if they are too old or were
5430 * never read.
5431 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005432 if (time_after(jiffies, conn->conn_info_timestamp +
5433 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005434 !conn->conn_info_timestamp) {
5435 struct hci_request req;
5436 struct hci_cp_read_tx_power req_txp_cp;
5437 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005438 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005439
5440 hci_req_init(&req, hdev);
5441 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5442 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5443 &req_rssi_cp);
5444
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005445 /* For LE links TX power does not change thus we don't need to
5446 * query for it once value is known.
5447 */
5448 if (!bdaddr_type_is_le(cp->addr.type) ||
5449 conn->tx_power == HCI_TX_POWER_INVALID) {
5450 req_txp_cp.handle = cpu_to_le16(conn->handle);
5451 req_txp_cp.type = 0x00;
5452 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5453 sizeof(req_txp_cp), &req_txp_cp);
5454 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005455
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005456 /* Max TX power needs to be read only once per connection */
5457 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5458 req_txp_cp.handle = cpu_to_le16(conn->handle);
5459 req_txp_cp.type = 0x01;
5460 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5461 sizeof(req_txp_cp), &req_txp_cp);
5462 }
5463
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005464 err = hci_req_run(&req, conn_info_refresh_complete);
5465 if (err < 0)
5466 goto unlock;
5467
5468 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5469 data, len);
5470 if (!cmd) {
5471 err = -ENOMEM;
5472 goto unlock;
5473 }
5474
5475 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005476 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005477 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005478
5479 conn->conn_info_timestamp = jiffies;
5480 } else {
5481 /* Cache is valid, just reply with values cached in hci_conn */
5482 rp.rssi = conn->rssi;
5483 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005484 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005485
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005486 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5487 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005488 }
5489
5490unlock:
5491 hci_dev_unlock(hdev);
5492 return err;
5493}
5494
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005495static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005496{
5497 struct hci_conn *conn = cmd->user_data;
5498 struct mgmt_rp_get_clock_info rp;
5499 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005500 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005501
5502 memset(&rp, 0, sizeof(rp));
5503 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5504
5505 if (status)
5506 goto complete;
5507
5508 hdev = hci_dev_get(cmd->index);
5509 if (hdev) {
5510 rp.local_clock = cpu_to_le32(hdev->clock);
5511 hci_dev_put(hdev);
5512 }
5513
5514 if (conn) {
5515 rp.piconet_clock = cpu_to_le32(conn->clock);
5516 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5517 }
5518
5519complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005520 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5521 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005522
5523 if (conn) {
5524 hci_conn_drop(conn);
5525 hci_conn_put(conn);
5526 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005527
5528 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005529}
5530
Marcel Holtmann1904a852015-01-11 13:50:44 -08005531static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005532{
Johan Hedberg95868422014-06-28 17:54:07 +03005533 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005534 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005535 struct hci_conn *conn;
5536
5537 BT_DBG("%s status %u", hdev->name, status);
5538
5539 hci_dev_lock(hdev);
5540
5541 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5542 if (!hci_cp)
5543 goto unlock;
5544
5545 if (hci_cp->which) {
5546 u16 handle = __le16_to_cpu(hci_cp->handle);
5547 conn = hci_conn_hash_lookup_handle(hdev, handle);
5548 } else {
5549 conn = NULL;
5550 }
5551
5552 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5553 if (!cmd)
5554 goto unlock;
5555
Johan Hedberg69487372014-12-05 13:36:07 +02005556 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005557 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005558
5559unlock:
5560 hci_dev_unlock(hdev);
5561}
5562
5563static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5564 u16 len)
5565{
5566 struct mgmt_cp_get_clock_info *cp = data;
5567 struct mgmt_rp_get_clock_info rp;
5568 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005569 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005570 struct hci_request req;
5571 struct hci_conn *conn;
5572 int err;
5573
5574 BT_DBG("%s", hdev->name);
5575
5576 memset(&rp, 0, sizeof(rp));
5577 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5578 rp.addr.type = cp->addr.type;
5579
5580 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005581 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5582 MGMT_STATUS_INVALID_PARAMS,
5583 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005584
5585 hci_dev_lock(hdev);
5586
5587 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005588 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5589 MGMT_STATUS_NOT_POWERED, &rp,
5590 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005591 goto unlock;
5592 }
5593
5594 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5595 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5596 &cp->addr.bdaddr);
5597 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005598 err = mgmt_cmd_complete(sk, hdev->id,
5599 MGMT_OP_GET_CLOCK_INFO,
5600 MGMT_STATUS_NOT_CONNECTED,
5601 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005602 goto unlock;
5603 }
5604 } else {
5605 conn = NULL;
5606 }
5607
5608 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5609 if (!cmd) {
5610 err = -ENOMEM;
5611 goto unlock;
5612 }
5613
Johan Hedberg69487372014-12-05 13:36:07 +02005614 cmd->cmd_complete = clock_info_cmd_complete;
5615
Johan Hedberg95868422014-06-28 17:54:07 +03005616 hci_req_init(&req, hdev);
5617
5618 memset(&hci_cp, 0, sizeof(hci_cp));
5619 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5620
5621 if (conn) {
5622 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005623 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005624
5625 hci_cp.handle = cpu_to_le16(conn->handle);
5626 hci_cp.which = 0x01; /* Piconet clock */
5627 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5628 }
5629
5630 err = hci_req_run(&req, get_clock_info_complete);
5631 if (err < 0)
5632 mgmt_pending_remove(cmd);
5633
5634unlock:
5635 hci_dev_unlock(hdev);
5636 return err;
5637}
5638
Johan Hedberg5a154e62014-12-19 22:26:02 +02005639static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5640{
5641 struct hci_conn *conn;
5642
5643 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5644 if (!conn)
5645 return false;
5646
5647 if (conn->dst_type != type)
5648 return false;
5649
5650 if (conn->state != BT_CONNECTED)
5651 return false;
5652
5653 return true;
5654}
5655
5656/* This function requires the caller holds hdev->lock */
5657static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5658 u8 addr_type, u8 auto_connect)
5659{
5660 struct hci_dev *hdev = req->hdev;
5661 struct hci_conn_params *params;
5662
5663 params = hci_conn_params_add(hdev, addr, addr_type);
5664 if (!params)
5665 return -EIO;
5666
5667 if (params->auto_connect == auto_connect)
5668 return 0;
5669
5670 list_del_init(&params->action);
5671
5672 switch (auto_connect) {
5673 case HCI_AUTO_CONN_DISABLED:
5674 case HCI_AUTO_CONN_LINK_LOSS:
5675 __hci_update_background_scan(req);
5676 break;
5677 case HCI_AUTO_CONN_REPORT:
5678 list_add(&params->action, &hdev->pend_le_reports);
5679 __hci_update_background_scan(req);
5680 break;
5681 case HCI_AUTO_CONN_DIRECT:
5682 case HCI_AUTO_CONN_ALWAYS:
5683 if (!is_connected(hdev, addr, addr_type)) {
5684 list_add(&params->action, &hdev->pend_le_conns);
5685 __hci_update_background_scan(req);
5686 }
5687 break;
5688 }
5689
5690 params->auto_connect = auto_connect;
5691
5692 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5693 auto_connect);
5694
5695 return 0;
5696}
5697
Marcel Holtmann8afef092014-06-29 22:28:34 +02005698static void device_added(struct sock *sk, struct hci_dev *hdev,
5699 bdaddr_t *bdaddr, u8 type, u8 action)
5700{
5701 struct mgmt_ev_device_added ev;
5702
5703 bacpy(&ev.addr.bdaddr, bdaddr);
5704 ev.addr.type = type;
5705 ev.action = action;
5706
5707 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5708}
5709
Marcel Holtmann1904a852015-01-11 13:50:44 -08005710static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005711{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005712 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005713
5714 BT_DBG("status 0x%02x", status);
5715
5716 hci_dev_lock(hdev);
5717
5718 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5719 if (!cmd)
5720 goto unlock;
5721
5722 cmd->cmd_complete(cmd, mgmt_status(status));
5723 mgmt_pending_remove(cmd);
5724
5725unlock:
5726 hci_dev_unlock(hdev);
5727}
5728
Marcel Holtmann2faade52014-06-29 19:44:03 +02005729static int add_device(struct sock *sk, struct hci_dev *hdev,
5730 void *data, u16 len)
5731{
5732 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005733 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005734 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005735 u8 auto_conn, addr_type;
5736 int err;
5737
5738 BT_DBG("%s", hdev->name);
5739
Johan Hedberg66593582014-07-09 12:59:14 +03005740 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005741 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005742 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5743 MGMT_STATUS_INVALID_PARAMS,
5744 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005745
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005746 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005747 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5748 MGMT_STATUS_INVALID_PARAMS,
5749 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005750
Johan Hedberg5a154e62014-12-19 22:26:02 +02005751 hci_req_init(&req, hdev);
5752
Marcel Holtmann2faade52014-06-29 19:44:03 +02005753 hci_dev_lock(hdev);
5754
Johan Hedberg5a154e62014-12-19 22:26:02 +02005755 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5756 if (!cmd) {
5757 err = -ENOMEM;
5758 goto unlock;
5759 }
5760
5761 cmd->cmd_complete = addr_cmd_complete;
5762
Johan Hedberg66593582014-07-09 12:59:14 +03005763 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005764 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005765 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005766 err = cmd->cmd_complete(cmd,
5767 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005768 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005769 goto unlock;
5770 }
5771
5772 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5773 cp->addr.type);
5774 if (err)
5775 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005776
Johan Hedberg5a154e62014-12-19 22:26:02 +02005777 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005778
Johan Hedberg66593582014-07-09 12:59:14 +03005779 goto added;
5780 }
5781
Marcel Holtmann2faade52014-06-29 19:44:03 +02005782 if (cp->addr.type == BDADDR_LE_PUBLIC)
5783 addr_type = ADDR_LE_DEV_PUBLIC;
5784 else
5785 addr_type = ADDR_LE_DEV_RANDOM;
5786
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005787 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005788 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005789 else if (cp->action == 0x01)
5790 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005791 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005792 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005793
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005794 /* If the connection parameters don't exist for this device,
5795 * they will be created and configured with defaults.
5796 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005797 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005798 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005799 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005800 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005801 goto unlock;
5802 }
5803
Johan Hedberg66593582014-07-09 12:59:14 +03005804added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005805 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5806
Johan Hedberg5a154e62014-12-19 22:26:02 +02005807 err = hci_req_run(&req, add_device_complete);
5808 if (err < 0) {
5809 /* ENODATA means no HCI commands were needed (e.g. if
5810 * the adapter is powered off).
5811 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005812 if (err == -ENODATA)
5813 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005814 mgmt_pending_remove(cmd);
5815 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005816
5817unlock:
5818 hci_dev_unlock(hdev);
5819 return err;
5820}
5821
Marcel Holtmann8afef092014-06-29 22:28:34 +02005822static void device_removed(struct sock *sk, struct hci_dev *hdev,
5823 bdaddr_t *bdaddr, u8 type)
5824{
5825 struct mgmt_ev_device_removed ev;
5826
5827 bacpy(&ev.addr.bdaddr, bdaddr);
5828 ev.addr.type = type;
5829
5830 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5831}
5832
Marcel Holtmann1904a852015-01-11 13:50:44 -08005833static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005834{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005835 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005836
5837 BT_DBG("status 0x%02x", status);
5838
5839 hci_dev_lock(hdev);
5840
5841 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5842 if (!cmd)
5843 goto unlock;
5844
5845 cmd->cmd_complete(cmd, mgmt_status(status));
5846 mgmt_pending_remove(cmd);
5847
5848unlock:
5849 hci_dev_unlock(hdev);
5850}
5851
Marcel Holtmann2faade52014-06-29 19:44:03 +02005852static int remove_device(struct sock *sk, struct hci_dev *hdev,
5853 void *data, u16 len)
5854{
5855 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005856 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005857 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005858 int err;
5859
5860 BT_DBG("%s", hdev->name);
5861
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005862 hci_req_init(&req, hdev);
5863
Marcel Holtmann2faade52014-06-29 19:44:03 +02005864 hci_dev_lock(hdev);
5865
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005866 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5867 if (!cmd) {
5868 err = -ENOMEM;
5869 goto unlock;
5870 }
5871
5872 cmd->cmd_complete = addr_cmd_complete;
5873
Marcel Holtmann2faade52014-06-29 19:44:03 +02005874 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005875 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005876 u8 addr_type;
5877
Johan Hedberg66593582014-07-09 12:59:14 +03005878 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005879 err = cmd->cmd_complete(cmd,
5880 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005881 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005882 goto unlock;
5883 }
5884
Johan Hedberg66593582014-07-09 12:59:14 +03005885 if (cp->addr.type == BDADDR_BREDR) {
5886 err = hci_bdaddr_list_del(&hdev->whitelist,
5887 &cp->addr.bdaddr,
5888 cp->addr.type);
5889 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005890 err = cmd->cmd_complete(cmd,
5891 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005892 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005893 goto unlock;
5894 }
5895
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005896 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005897
Johan Hedberg66593582014-07-09 12:59:14 +03005898 device_removed(sk, hdev, &cp->addr.bdaddr,
5899 cp->addr.type);
5900 goto complete;
5901 }
5902
Marcel Holtmann2faade52014-06-29 19:44:03 +02005903 if (cp->addr.type == BDADDR_LE_PUBLIC)
5904 addr_type = ADDR_LE_DEV_PUBLIC;
5905 else
5906 addr_type = ADDR_LE_DEV_RANDOM;
5907
Johan Hedbergc71593d2014-07-02 17:37:28 +03005908 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5909 addr_type);
5910 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005911 err = cmd->cmd_complete(cmd,
5912 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005913 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005914 goto unlock;
5915 }
5916
5917 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005918 err = cmd->cmd_complete(cmd,
5919 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005920 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005921 goto unlock;
5922 }
5923
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005924 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005925 list_del(&params->list);
5926 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005927 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005928
5929 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005930 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005931 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005932 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005933
Marcel Holtmann2faade52014-06-29 19:44:03 +02005934 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005935 err = cmd->cmd_complete(cmd,
5936 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005937 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005938 goto unlock;
5939 }
5940
Johan Hedberg66593582014-07-09 12:59:14 +03005941 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5942 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5943 list_del(&b->list);
5944 kfree(b);
5945 }
5946
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005947 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005948
Johan Hedberg19de0822014-07-06 13:06:51 +03005949 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5950 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5951 continue;
5952 device_removed(sk, hdev, &p->addr, p->addr_type);
5953 list_del(&p->action);
5954 list_del(&p->list);
5955 kfree(p);
5956 }
5957
5958 BT_DBG("All LE connection parameters were removed");
5959
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005960 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005961 }
5962
Johan Hedberg66593582014-07-09 12:59:14 +03005963complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005964 err = hci_req_run(&req, remove_device_complete);
5965 if (err < 0) {
5966 /* ENODATA means no HCI commands were needed (e.g. if
5967 * the adapter is powered off).
5968 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005969 if (err == -ENODATA)
5970 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005971 mgmt_pending_remove(cmd);
5972 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005973
5974unlock:
5975 hci_dev_unlock(hdev);
5976 return err;
5977}
5978
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005979static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5980 u16 len)
5981{
5982 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005983 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5984 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005985 u16 param_count, expected_len;
5986 int i;
5987
5988 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005989 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5990 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005991
5992 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005993 if (param_count > max_param_count) {
5994 BT_ERR("load_conn_param: too big param_count value %u",
5995 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005996 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5997 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005998 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005999
6000 expected_len = sizeof(*cp) + param_count *
6001 sizeof(struct mgmt_conn_param);
6002 if (expected_len != len) {
6003 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6004 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006005 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6006 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006007 }
6008
6009 BT_DBG("%s param_count %u", hdev->name, param_count);
6010
6011 hci_dev_lock(hdev);
6012
6013 hci_conn_params_clear_disabled(hdev);
6014
6015 for (i = 0; i < param_count; i++) {
6016 struct mgmt_conn_param *param = &cp->params[i];
6017 struct hci_conn_params *hci_param;
6018 u16 min, max, latency, timeout;
6019 u8 addr_type;
6020
6021 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6022 param->addr.type);
6023
6024 if (param->addr.type == BDADDR_LE_PUBLIC) {
6025 addr_type = ADDR_LE_DEV_PUBLIC;
6026 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6027 addr_type = ADDR_LE_DEV_RANDOM;
6028 } else {
6029 BT_ERR("Ignoring invalid connection parameters");
6030 continue;
6031 }
6032
6033 min = le16_to_cpu(param->min_interval);
6034 max = le16_to_cpu(param->max_interval);
6035 latency = le16_to_cpu(param->latency);
6036 timeout = le16_to_cpu(param->timeout);
6037
6038 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6039 min, max, latency, timeout);
6040
6041 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6042 BT_ERR("Ignoring invalid connection parameters");
6043 continue;
6044 }
6045
6046 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6047 addr_type);
6048 if (!hci_param) {
6049 BT_ERR("Failed to add connection parameters");
6050 continue;
6051 }
6052
6053 hci_param->conn_min_interval = min;
6054 hci_param->conn_max_interval = max;
6055 hci_param->conn_latency = latency;
6056 hci_param->supervision_timeout = timeout;
6057 }
6058
6059 hci_dev_unlock(hdev);
6060
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006061 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6062 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006063}
6064
Marcel Holtmanndbece372014-07-04 18:11:55 +02006065static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6066 void *data, u16 len)
6067{
6068 struct mgmt_cp_set_external_config *cp = data;
6069 bool changed;
6070 int err;
6071
6072 BT_DBG("%s", hdev->name);
6073
6074 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006075 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6076 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006077
6078 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006079 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6080 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006081
6082 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006083 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6084 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006085
6086 hci_dev_lock(hdev);
6087
6088 if (cp->config)
6089 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6090 &hdev->dev_flags);
6091 else
6092 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6093 &hdev->dev_flags);
6094
6095 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6096 if (err < 0)
6097 goto unlock;
6098
6099 if (!changed)
6100 goto unlock;
6101
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006102 err = new_options(hdev, sk);
6103
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006104 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006105 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006106
6107 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006108 hci_dev_set_flag(hdev, HCI_CONFIG);
6109 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006110
6111 queue_work(hdev->req_workqueue, &hdev->power_on);
6112 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006113 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006114 mgmt_index_added(hdev);
6115 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006116 }
6117
6118unlock:
6119 hci_dev_unlock(hdev);
6120 return err;
6121}
6122
Marcel Holtmann9713c172014-07-06 12:11:15 +02006123static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6124 void *data, u16 len)
6125{
6126 struct mgmt_cp_set_public_address *cp = data;
6127 bool changed;
6128 int err;
6129
6130 BT_DBG("%s", hdev->name);
6131
6132 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006133 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6134 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006135
6136 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006137 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6138 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006139
6140 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006141 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6142 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006143
6144 hci_dev_lock(hdev);
6145
6146 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6147 bacpy(&hdev->public_addr, &cp->bdaddr);
6148
6149 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6150 if (err < 0)
6151 goto unlock;
6152
6153 if (!changed)
6154 goto unlock;
6155
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006156 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006157 err = new_options(hdev, sk);
6158
6159 if (is_configured(hdev)) {
6160 mgmt_index_removed(hdev);
6161
6162 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6163
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006164 hci_dev_set_flag(hdev, HCI_CONFIG);
6165 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006166
6167 queue_work(hdev->req_workqueue, &hdev->power_on);
6168 }
6169
6170unlock:
6171 hci_dev_unlock(hdev);
6172 return err;
6173}
6174
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006175static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006176 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006177 { read_version, MGMT_READ_VERSION_SIZE,
6178 HCI_MGMT_NO_HDEV },
6179 { read_commands, MGMT_READ_COMMANDS_SIZE,
6180 HCI_MGMT_NO_HDEV },
6181 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6182 HCI_MGMT_NO_HDEV },
6183 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6184 { set_powered, MGMT_SETTING_SIZE, 0 },
6185 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6186 { set_connectable, MGMT_SETTING_SIZE, 0 },
6187 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6188 { set_bondable, MGMT_SETTING_SIZE, 0 },
6189 { set_link_security, MGMT_SETTING_SIZE, 0 },
6190 { set_ssp, MGMT_SETTING_SIZE, 0 },
6191 { set_hs, MGMT_SETTING_SIZE, 0 },
6192 { set_le, MGMT_SETTING_SIZE, 0 },
6193 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6194 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6195 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6196 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6197 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6198 HCI_MGMT_VAR_LEN },
6199 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6200 HCI_MGMT_VAR_LEN },
6201 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6202 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6203 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6204 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6205 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6206 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6207 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6208 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6209 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6210 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6211 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6212 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6213 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6214 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6215 HCI_MGMT_VAR_LEN },
6216 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6217 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6218 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6219 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6220 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6221 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6222 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6223 { set_advertising, MGMT_SETTING_SIZE, 0 },
6224 { set_bredr, MGMT_SETTING_SIZE, 0 },
6225 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6226 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6227 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6228 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6229 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6230 { load_irks, MGMT_LOAD_IRKS_SIZE,
6231 HCI_MGMT_VAR_LEN },
6232 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6233 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6234 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6235 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6236 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6237 HCI_MGMT_VAR_LEN },
6238 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6239 HCI_MGMT_NO_HDEV },
6240 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6241 HCI_MGMT_UNCONFIGURED },
6242 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6243 HCI_MGMT_UNCONFIGURED },
6244 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6245 HCI_MGMT_UNCONFIGURED },
6246 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6247 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006248};
6249
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006250int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6251 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006252{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006253 void *buf;
6254 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006255 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006256 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006257 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006258 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006259 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006260 int err;
6261
6262 BT_DBG("got %zu bytes", msglen);
6263
6264 if (msglen < sizeof(*hdr))
6265 return -EINVAL;
6266
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006267 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006268 if (!buf)
6269 return -ENOMEM;
6270
Al Viro6ce8e9c2014-04-06 21:25:44 -04006271 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006272 err = -EFAULT;
6273 goto done;
6274 }
6275
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006276 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006277 opcode = __le16_to_cpu(hdr->opcode);
6278 index = __le16_to_cpu(hdr->index);
6279 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006280
6281 if (len != msglen - sizeof(*hdr)) {
6282 err = -EINVAL;
6283 goto done;
6284 }
6285
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006286 if (opcode >= chan->handler_count ||
6287 chan->handlers[opcode].func == NULL) {
6288 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006289 err = mgmt_cmd_status(sk, index, opcode,
6290 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006291 goto done;
6292 }
6293
6294 handler = &chan->handlers[opcode];
6295
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006296 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006297 hdev = hci_dev_get(index);
6298 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006299 err = mgmt_cmd_status(sk, index, opcode,
6300 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006301 goto done;
6302 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006303
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006304 if (hci_dev_test_flag(hdev, HCI_SETUP) ||
6305 hci_dev_test_flag(hdev, HCI_CONFIG) ||
6306 hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006307 err = mgmt_cmd_status(sk, index, opcode,
6308 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006309 goto done;
6310 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006311
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006312 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006313 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006314 err = mgmt_cmd_status(sk, index, opcode,
6315 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006316 goto done;
6317 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006318 }
6319
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006320 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6321 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006322 err = mgmt_cmd_status(sk, index, opcode,
6323 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006324 goto done;
6325 }
6326
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006327 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6328 if ((var_len && len < handler->data_len) ||
6329 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006330 err = mgmt_cmd_status(sk, index, opcode,
6331 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006332 goto done;
6333 }
6334
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006335 if (hdev)
6336 mgmt_init_hdev(sk, hdev);
6337
6338 cp = buf + sizeof(*hdr);
6339
Johan Hedbergbe22b542012-03-01 22:24:41 +02006340 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006341 if (err < 0)
6342 goto done;
6343
Johan Hedberg03811012010-12-08 00:21:06 +02006344 err = msglen;
6345
6346done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006347 if (hdev)
6348 hci_dev_put(hdev);
6349
Johan Hedberg03811012010-12-08 00:21:06 +02006350 kfree(buf);
6351 return err;
6352}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006353
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006354void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006355{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006356 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006357 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006358
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006359 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6360 return;
6361
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006362 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006363 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6364 else
6365 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006366}
6367
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006368void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006369{
Johan Hedberg5f159032012-03-02 03:13:19 +02006370 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006371
Marcel Holtmann1514b892013-10-06 08:25:01 -07006372 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006373 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006374
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006375 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6376 return;
6377
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006378 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006379
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006380 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmannedd38962014-07-02 21:30:55 +02006381 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6382 else
6383 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006384}
6385
Andre Guedes6046dc32014-02-26 20:21:51 -03006386/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006387static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006388{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006389 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006390 struct hci_conn_params *p;
6391
6392 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006393 /* Needed for AUTO_OFF case where might not "really"
6394 * have been powered off.
6395 */
6396 list_del_init(&p->action);
6397
6398 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006399 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006400 case HCI_AUTO_CONN_ALWAYS:
6401 list_add(&p->action, &hdev->pend_le_conns);
6402 break;
6403 case HCI_AUTO_CONN_REPORT:
6404 list_add(&p->action, &hdev->pend_le_reports);
6405 break;
6406 default:
6407 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006408 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006409 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006410
Johan Hedberg2cf22212014-12-19 22:26:00 +02006411 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006412}
6413
Marcel Holtmann1904a852015-01-11 13:50:44 -08006414static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006415{
6416 struct cmd_lookup match = { NULL, hdev };
6417
6418 BT_DBG("status 0x%02x", status);
6419
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006420 if (!status) {
6421 /* Register the available SMP channels (BR/EDR and LE) only
6422 * when successfully powering on the controller. This late
6423 * registration is required so that LE SMP can clearly
6424 * decide if the public address or static address is used.
6425 */
6426 smp_register(hdev);
6427 }
6428
Johan Hedberg229ab392013-03-15 17:06:53 -05006429 hci_dev_lock(hdev);
6430
6431 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6432
6433 new_settings(hdev, match.sk);
6434
6435 hci_dev_unlock(hdev);
6436
6437 if (match.sk)
6438 sock_put(match.sk);
6439}
6440
Johan Hedberg70da6242013-03-15 17:06:51 -05006441static int powered_update_hci(struct hci_dev *hdev)
6442{
Johan Hedberg890ea892013-03-15 17:06:52 -05006443 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006444 u8 link_sec;
6445
Johan Hedberg890ea892013-03-15 17:06:52 -05006446 hci_req_init(&req, hdev);
6447
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006448 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05006449 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006450 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006451
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006452 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006453
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006454 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6455 u8 support = 0x01;
6456
6457 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6458 sizeof(support), &support);
6459 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006460 }
6461
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006462 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03006463 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006464 struct hci_cp_write_le_host_supported cp;
6465
Marcel Holtmann32226e42014-07-24 20:04:16 +02006466 cp.le = 0x01;
6467 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006468
6469 /* Check first if we already have the right
6470 * host state (host features set)
6471 */
6472 if (cp.le != lmp_host_le_capable(hdev) ||
6473 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006474 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6475 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006476 }
6477
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006478 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006479 /* Make sure the controller has a good default for
6480 * advertising data. This also applies to the case
6481 * where BR/EDR was toggled during the AUTO_OFF phase.
6482 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006483 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006484 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006485 update_scan_rsp_data(&req);
6486 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006487
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006488 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006489 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006490
6491 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006492 }
6493
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006494 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05006495 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006496 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6497 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006498
6499 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006500 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006501 write_fast_connectable(&req, true);
6502 else
6503 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006504 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006505 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006506 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006507 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006508 }
6509
Johan Hedberg229ab392013-03-15 17:06:53 -05006510 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006511}
6512
Johan Hedberg744cf192011-11-08 20:40:14 +02006513int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006514{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006515 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006516 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006517 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006518
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006519 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006520 return 0;
6521
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006522 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006523 if (powered_update_hci(hdev) == 0)
6524 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006525
Johan Hedberg229ab392013-03-15 17:06:53 -05006526 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6527 &match);
6528 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006529 }
6530
Johan Hedberg229ab392013-03-15 17:06:53 -05006531 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006532
6533 /* If the power off is because of hdev unregistration let
6534 * use the appropriate INVALID_INDEX status. Otherwise use
6535 * NOT_POWERED. We cover both scenarios here since later in
6536 * mgmt_index_removed() any hci_conn callbacks will have already
6537 * been triggered, potentially causing misleading DISCONNECTED
6538 * status responses.
6539 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006540 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02006541 status = MGMT_STATUS_INVALID_INDEX;
6542 else
6543 status = MGMT_STATUS_NOT_POWERED;
6544
6545 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006546
6547 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6548 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6549 zero_cod, sizeof(zero_cod), NULL);
6550
6551new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006552 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006553
6554 if (match.sk)
6555 sock_put(match.sk);
6556
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006557 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006558}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006559
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006560void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006561{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006562 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006563 u8 status;
6564
6565 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6566 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006567 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006568
6569 if (err == -ERFKILL)
6570 status = MGMT_STATUS_RFKILLED;
6571 else
6572 status = MGMT_STATUS_FAILED;
6573
Johan Hedberga69e8372015-03-06 21:08:53 +02006574 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006575
6576 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006577}
6578
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006579void mgmt_discoverable_timeout(struct hci_dev *hdev)
6580{
6581 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006582
6583 hci_dev_lock(hdev);
6584
6585 /* When discoverable timeout triggers, then just make sure
6586 * the limited discoverable flag is cleared. Even in the case
6587 * of a timeout triggered from general discoverable, it is
6588 * safe to unconditionally clear the flag.
6589 */
6590 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006591 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006592
6593 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006594 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03006595 u8 scan = SCAN_PAGE;
6596 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6597 sizeof(scan), &scan);
6598 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006599 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006600 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006601 hci_req_run(&req, NULL);
6602
6603 hdev->discov_timeout = 0;
6604
Johan Hedberg9a43e252013-10-20 19:00:07 +03006605 new_settings(hdev, NULL);
6606
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006607 hci_dev_unlock(hdev);
6608}
6609
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006610void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6611 bool persistent)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006612{
Johan Hedberg86742e12011-11-07 23:13:38 +02006613 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006614
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006615 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006616
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006617 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006618 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006619 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006620 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006621 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006622 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006623
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006624 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02006625}
Johan Hedbergf7520542011-01-20 12:34:39 +02006626
Johan Hedbergd7b25452014-05-23 13:19:53 +03006627static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6628{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006629 switch (ltk->type) {
6630 case SMP_LTK:
6631 case SMP_LTK_SLAVE:
6632 if (ltk->authenticated)
6633 return MGMT_LTK_AUTHENTICATED;
6634 return MGMT_LTK_UNAUTHENTICATED;
6635 case SMP_LTK_P256:
6636 if (ltk->authenticated)
6637 return MGMT_LTK_P256_AUTH;
6638 return MGMT_LTK_P256_UNAUTH;
6639 case SMP_LTK_P256_DEBUG:
6640 return MGMT_LTK_P256_DEBUG;
6641 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006642
6643 return MGMT_LTK_UNAUTHENTICATED;
6644}
6645
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006646void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006647{
6648 struct mgmt_ev_new_long_term_key ev;
6649
6650 memset(&ev, 0, sizeof(ev));
6651
Marcel Holtmann5192d302014-02-19 17:11:58 -08006652 /* Devices using resolvable or non-resolvable random addresses
6653 * without providing an indentity resolving key don't require
6654 * to store long term keys. Their addresses will change the
6655 * next time around.
6656 *
6657 * Only when a remote device provides an identity address
6658 * make sure the long term key is stored. If the remote
6659 * identity is known, the long term keys are internally
6660 * mapped to the identity address. So allow static random
6661 * and public addresses here.
6662 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006663 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6664 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6665 ev.store_hint = 0x00;
6666 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006667 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006668
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006669 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006670 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006671 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006672 ev.key.enc_size = key->enc_size;
6673 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006674 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006675
Johan Hedberg2ceba532014-06-16 19:25:16 +03006676 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006677 ev.key.master = 1;
6678
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006679 memcpy(ev.key.val, key->val, sizeof(key->val));
6680
Marcel Holtmann083368f2013-10-15 14:26:29 -07006681 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006682}
6683
Johan Hedberg95fbac82014-02-19 15:18:31 +02006684void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6685{
6686 struct mgmt_ev_new_irk ev;
6687
6688 memset(&ev, 0, sizeof(ev));
6689
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006690 /* For identity resolving keys from devices that are already
6691 * using a public address or static random address, do not
6692 * ask for storing this key. The identity resolving key really
6693 * is only mandatory for devices using resovlable random
6694 * addresses.
6695 *
6696 * Storing all identity resolving keys has the downside that
6697 * they will be also loaded on next boot of they system. More
6698 * identity resolving keys, means more time during scanning is
6699 * needed to actually resolve these addresses.
6700 */
6701 if (bacmp(&irk->rpa, BDADDR_ANY))
6702 ev.store_hint = 0x01;
6703 else
6704 ev.store_hint = 0x00;
6705
Johan Hedberg95fbac82014-02-19 15:18:31 +02006706 bacpy(&ev.rpa, &irk->rpa);
6707 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6708 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6709 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6710
6711 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6712}
6713
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006714void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6715 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006716{
6717 struct mgmt_ev_new_csrk ev;
6718
6719 memset(&ev, 0, sizeof(ev));
6720
6721 /* Devices using resolvable or non-resolvable random addresses
6722 * without providing an indentity resolving key don't require
6723 * to store signature resolving keys. Their addresses will change
6724 * the next time around.
6725 *
6726 * Only when a remote device provides an identity address
6727 * make sure the signature resolving key is stored. So allow
6728 * static random and public addresses here.
6729 */
6730 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6731 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6732 ev.store_hint = 0x00;
6733 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006734 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006735
6736 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6737 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006738 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006739 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6740
6741 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6742}
6743
Andre Guedesffb5a8272014-07-01 18:10:11 -03006744void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006745 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6746 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006747{
6748 struct mgmt_ev_new_conn_param ev;
6749
Johan Hedbergc103aea2014-07-02 17:37:34 +03006750 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6751 return;
6752
Andre Guedesffb5a8272014-07-01 18:10:11 -03006753 memset(&ev, 0, sizeof(ev));
6754 bacpy(&ev.addr.bdaddr, bdaddr);
6755 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006756 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006757 ev.min_interval = cpu_to_le16(min_interval);
6758 ev.max_interval = cpu_to_le16(max_interval);
6759 ev.latency = cpu_to_le16(latency);
6760 ev.timeout = cpu_to_le16(timeout);
6761
6762 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6763}
6764
Marcel Holtmann94933992013-10-15 10:26:39 -07006765static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6766 u8 data_len)
6767{
6768 eir[eir_len++] = sizeof(type) + data_len;
6769 eir[eir_len++] = type;
6770 memcpy(&eir[eir_len], data, data_len);
6771 eir_len += data_len;
6772
6773 return eir_len;
6774}
6775
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006776void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6777 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006778{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006779 char buf[512];
6780 struct mgmt_ev_device_connected *ev = (void *) buf;
6781 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006782
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006783 bacpy(&ev->addr.bdaddr, &conn->dst);
6784 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006785
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006786 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006787
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006788 /* We must ensure that the EIR Data fields are ordered and
6789 * unique. Keep it simple for now and avoid the problem by not
6790 * adding any BR/EDR data to the LE adv.
6791 */
6792 if (conn->le_adv_data_len > 0) {
6793 memcpy(&ev->eir[eir_len],
6794 conn->le_adv_data, conn->le_adv_data_len);
6795 eir_len = conn->le_adv_data_len;
6796 } else {
6797 if (name_len > 0)
6798 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6799 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006800
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006801 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006802 eir_len = eir_append_data(ev->eir, eir_len,
6803 EIR_CLASS_OF_DEV,
6804 conn->dev_class, 3);
6805 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006806
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006807 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006808
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006809 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6810 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006811}
6812
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006813static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006814{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006815 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006816
Johan Hedbergf5818c22014-12-05 13:36:02 +02006817 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006818
6819 *sk = cmd->sk;
6820 sock_hold(*sk);
6821
Johan Hedberga664b5b2011-02-19 12:06:02 -03006822 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006823}
6824
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006825static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006826{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006827 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006828 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006829
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006830 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6831
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006832 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006833 mgmt_pending_remove(cmd);
6834}
6835
Johan Hedberg84c61d92014-08-01 11:13:30 +03006836bool mgmt_powering_down(struct hci_dev *hdev)
6837{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006838 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006839 struct mgmt_mode *cp;
6840
6841 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6842 if (!cmd)
6843 return false;
6844
6845 cp = cmd->param;
6846 if (!cp->val)
6847 return true;
6848
6849 return false;
6850}
6851
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006852void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006853 u8 link_type, u8 addr_type, u8 reason,
6854 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006855{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006856 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006857 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006858
Johan Hedberg84c61d92014-08-01 11:13:30 +03006859 /* The connection is still in hci_conn_hash so test for 1
6860 * instead of 0 to know if this is the last one.
6861 */
6862 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6863 cancel_delayed_work(&hdev->power_off);
6864 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006865 }
6866
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006867 if (!mgmt_connected)
6868 return;
6869
Andre Guedes57eb7762013-10-30 19:01:41 -03006870 if (link_type != ACL_LINK && link_type != LE_LINK)
6871 return;
6872
Johan Hedberg744cf192011-11-08 20:40:14 +02006873 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006874
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006875 bacpy(&ev.addr.bdaddr, bdaddr);
6876 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6877 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006878
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006879 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006880
6881 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006882 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006883
Johan Hedberg124f6e32012-02-09 13:50:12 +02006884 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006885 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006886}
6887
Marcel Holtmann78929242013-10-06 23:55:47 -07006888void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6889 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006890{
Andre Guedes3655bba2013-10-30 19:01:40 -03006891 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6892 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006893 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006894
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006895 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6896 hdev);
6897
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006898 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006899 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006900 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006901
Andre Guedes3655bba2013-10-30 19:01:40 -03006902 cp = cmd->param;
6903
6904 if (bacmp(bdaddr, &cp->addr.bdaddr))
6905 return;
6906
6907 if (cp->addr.type != bdaddr_type)
6908 return;
6909
Johan Hedbergf5818c22014-12-05 13:36:02 +02006910 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006911 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006912}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006913
Marcel Holtmann445608d2013-10-06 23:55:48 -07006914void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6915 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006916{
6917 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006918
Johan Hedberg84c61d92014-08-01 11:13:30 +03006919 /* The connection is still in hci_conn_hash so test for 1
6920 * instead of 0 to know if this is the last one.
6921 */
6922 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6923 cancel_delayed_work(&hdev->power_off);
6924 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006925 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006926
Johan Hedberg4c659c32011-11-07 23:13:39 +02006927 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006928 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006929 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006930
Marcel Holtmann445608d2013-10-06 23:55:48 -07006931 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006932}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006933
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006934void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006935{
6936 struct mgmt_ev_pin_code_request ev;
6937
Johan Hedbergd8457692012-02-17 14:24:57 +02006938 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006939 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006940 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006941
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006942 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006943}
6944
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006945void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6946 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006947{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006948 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006949
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006950 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006951 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006952 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006953
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006954 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006955 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006956}
6957
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006958void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6959 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006960{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006961 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006962
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006963 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006964 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006965 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006966
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006967 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006968 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006969}
Johan Hedberga5c29682011-02-19 12:05:57 -03006970
Johan Hedberg744cf192011-11-08 20:40:14 +02006971int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006972 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006973 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006974{
6975 struct mgmt_ev_user_confirm_request ev;
6976
Johan Hedberg744cf192011-11-08 20:40:14 +02006977 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006978
Johan Hedberg272d90d2012-02-09 15:26:12 +02006979 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006980 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006981 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006982 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006983
Johan Hedberg744cf192011-11-08 20:40:14 +02006984 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006985 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006986}
6987
Johan Hedberg272d90d2012-02-09 15:26:12 +02006988int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006989 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006990{
6991 struct mgmt_ev_user_passkey_request ev;
6992
6993 BT_DBG("%s", hdev->name);
6994
Johan Hedberg272d90d2012-02-09 15:26:12 +02006995 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006996 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006997
6998 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006999 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007000}
7001
Brian Gix0df4c182011-11-16 13:53:13 -08007002static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007003 u8 link_type, u8 addr_type, u8 status,
7004 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007005{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007006 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007007
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007008 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007009 if (!cmd)
7010 return -ENOENT;
7011
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007012 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007013 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007014
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007015 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007016}
7017
Johan Hedberg744cf192011-11-08 20:40:14 +02007018int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007019 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007020{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007021 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007022 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007023}
7024
Johan Hedberg272d90d2012-02-09 15:26:12 +02007025int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007026 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007027{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007028 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007029 status,
7030 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007031}
Johan Hedberg2a611692011-02-19 12:06:00 -03007032
Brian Gix604086b2011-11-23 08:28:33 -08007033int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007034 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007035{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007036 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007037 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007038}
7039
Johan Hedberg272d90d2012-02-09 15:26:12 +02007040int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007041 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007042{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007043 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007044 status,
7045 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007046}
7047
Johan Hedberg92a25252012-09-06 18:39:26 +03007048int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7049 u8 link_type, u8 addr_type, u32 passkey,
7050 u8 entered)
7051{
7052 struct mgmt_ev_passkey_notify ev;
7053
7054 BT_DBG("%s", hdev->name);
7055
7056 bacpy(&ev.addr.bdaddr, bdaddr);
7057 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7058 ev.passkey = __cpu_to_le32(passkey);
7059 ev.entered = entered;
7060
7061 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7062}
7063
Johan Hedberge1e930f2014-09-08 17:09:49 -07007064void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007065{
7066 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007067 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007068 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007069
Johan Hedberge1e930f2014-09-08 17:09:49 -07007070 bacpy(&ev.addr.bdaddr, &conn->dst);
7071 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7072 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007073
Johan Hedberge1e930f2014-09-08 17:09:49 -07007074 cmd = find_pairing(conn);
7075
7076 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7077 cmd ? cmd->sk : NULL);
7078
Johan Hedberga511b352014-12-11 21:45:45 +02007079 if (cmd) {
7080 cmd->cmd_complete(cmd, status);
7081 mgmt_pending_remove(cmd);
7082 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007083}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007084
Marcel Holtmann464996a2013-10-15 14:26:24 -07007085void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007086{
7087 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007088 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007089
7090 if (status) {
7091 u8 mgmt_err = mgmt_status(status);
7092 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007093 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007094 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007095 }
7096
Marcel Holtmann464996a2013-10-15 14:26:24 -07007097 if (test_bit(HCI_AUTH, &hdev->flags))
7098 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7099 &hdev->dev_flags);
7100 else
7101 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7102 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007103
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007104 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007105 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007106
Johan Hedberg47990ea2012-02-22 11:58:37 +02007107 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007108 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007109
7110 if (match.sk)
7111 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007112}
7113
Johan Hedberg890ea892013-03-15 17:06:52 -05007114static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007115{
Johan Hedberg890ea892013-03-15 17:06:52 -05007116 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007117 struct hci_cp_write_eir cp;
7118
Johan Hedberg976eb202012-10-24 21:12:01 +03007119 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007120 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007121
Johan Hedbergc80da272012-02-22 15:38:48 +02007122 memset(hdev->eir, 0, sizeof(hdev->eir));
7123
Johan Hedbergcacaf522012-02-21 00:52:42 +02007124 memset(&cp, 0, sizeof(cp));
7125
Johan Hedberg890ea892013-03-15 17:06:52 -05007126 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007127}
7128
Marcel Holtmann3e248562013-10-15 14:26:25 -07007129void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007130{
7131 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007132 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007133 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007134
7135 if (status) {
7136 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007137
7138 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007139 &hdev->dev_flags)) {
7140 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007141 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007142 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007143
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007144 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7145 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007146 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007147 }
7148
7149 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007150 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007151 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007152 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7153 if (!changed)
7154 changed = test_and_clear_bit(HCI_HS_ENABLED,
7155 &hdev->dev_flags);
7156 else
7157 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007158 }
7159
7160 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7161
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007162 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007163 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007164
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007165 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007166 sock_put(match.sk);
7167
Johan Hedberg890ea892013-03-15 17:06:52 -05007168 hci_req_init(&req, hdev);
7169
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007170 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7171 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007172 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7173 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007174 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007175 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007176 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007177 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007178
7179 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007180}
7181
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007182static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007183{
7184 struct cmd_lookup *match = data;
7185
Johan Hedberg90e70452012-02-23 23:09:40 +02007186 if (match->sk == NULL) {
7187 match->sk = cmd->sk;
7188 sock_hold(match->sk);
7189 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007190}
7191
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007192void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7193 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007194{
Johan Hedberg90e70452012-02-23 23:09:40 +02007195 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007196
Johan Hedberg92da6092013-03-15 17:06:55 -05007197 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7198 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7199 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007200
7201 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007202 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7203 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007204
7205 if (match.sk)
7206 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007207}
7208
Marcel Holtmann7667da32013-10-15 14:26:27 -07007209void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007210{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007211 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007212 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007213
Johan Hedberg13928972013-03-15 17:07:00 -05007214 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007215 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007216
7217 memset(&ev, 0, sizeof(ev));
7218 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007219 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007220
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007221 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007222 if (!cmd) {
7223 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007224
Johan Hedberg13928972013-03-15 17:07:00 -05007225 /* If this is a HCI command related to powering on the
7226 * HCI dev don't send any mgmt signals.
7227 */
7228 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007229 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007230 }
7231
Marcel Holtmann7667da32013-10-15 14:26:27 -07007232 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7233 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007234}
Szymon Jancc35938b2011-03-22 13:12:21 +01007235
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007236void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007237 u8 *rand192, u8 *hash256, u8 *rand256,
7238 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007239{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007240 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007241
Johan Hedberg744cf192011-11-08 20:40:14 +02007242 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007243
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007244 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007245 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007246 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007247
7248 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007249 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7250 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007251 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007252 struct mgmt_rp_read_local_oob_data rp;
7253 size_t rp_size = sizeof(rp);
7254
7255 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7256 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7257
Johan Hedberg710f11c2014-05-26 11:21:22 +03007258 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007259 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007260 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007261 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007262 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007263 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007264
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007265 mgmt_cmd_complete(cmd->sk, hdev->id,
7266 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7267 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007268 }
7269
7270 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007271}
Johan Hedberge17acd42011-03-30 23:57:16 +03007272
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007273static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7274{
7275 int i;
7276
7277 for (i = 0; i < uuid_count; i++) {
7278 if (!memcmp(uuid, uuids[i], 16))
7279 return true;
7280 }
7281
7282 return false;
7283}
7284
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007285static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7286{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007287 u16 parsed = 0;
7288
7289 while (parsed < eir_len) {
7290 u8 field_len = eir[0];
7291 u8 uuid[16];
7292 int i;
7293
7294 if (field_len == 0)
7295 break;
7296
7297 if (eir_len - parsed < field_len + 1)
7298 break;
7299
7300 switch (eir[1]) {
7301 case EIR_UUID16_ALL:
7302 case EIR_UUID16_SOME:
7303 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007304 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007305 uuid[13] = eir[i + 3];
7306 uuid[12] = eir[i + 2];
7307 if (has_uuid(uuid, uuid_count, uuids))
7308 return true;
7309 }
7310 break;
7311 case EIR_UUID32_ALL:
7312 case EIR_UUID32_SOME:
7313 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007314 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007315 uuid[15] = eir[i + 5];
7316 uuid[14] = eir[i + 4];
7317 uuid[13] = eir[i + 3];
7318 uuid[12] = eir[i + 2];
7319 if (has_uuid(uuid, uuid_count, uuids))
7320 return true;
7321 }
7322 break;
7323 case EIR_UUID128_ALL:
7324 case EIR_UUID128_SOME:
7325 for (i = 0; i + 17 <= field_len; i += 16) {
7326 memcpy(uuid, eir + i + 2, 16);
7327 if (has_uuid(uuid, uuid_count, uuids))
7328 return true;
7329 }
7330 break;
7331 }
7332
7333 parsed += field_len + 1;
7334 eir += field_len + 1;
7335 }
7336
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007337 return false;
7338}
7339
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007340static void restart_le_scan(struct hci_dev *hdev)
7341{
7342 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007343 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007344 return;
7345
7346 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7347 hdev->discovery.scan_start +
7348 hdev->discovery.scan_duration))
7349 return;
7350
7351 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7352 DISCOV_LE_RESTART_DELAY);
7353}
7354
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007355static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7356 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7357{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007358 /* If a RSSI threshold has been specified, and
7359 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7360 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7361 * is set, let it through for further processing, as we might need to
7362 * restart the scan.
7363 *
7364 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7365 * the results are also dropped.
7366 */
7367 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7368 (rssi == HCI_RSSI_INVALID ||
7369 (rssi < hdev->discovery.rssi &&
7370 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7371 return false;
7372
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007373 if (hdev->discovery.uuid_count != 0) {
7374 /* If a list of UUIDs is provided in filter, results with no
7375 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007376 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007377 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7378 hdev->discovery.uuids) &&
7379 !eir_has_uuids(scan_rsp, scan_rsp_len,
7380 hdev->discovery.uuid_count,
7381 hdev->discovery.uuids))
7382 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007383 }
7384
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007385 /* If duplicate filtering does not report RSSI changes, then restart
7386 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007387 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007388 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7389 restart_le_scan(hdev);
7390
7391 /* Validate RSSI value against the RSSI threshold once more. */
7392 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7393 rssi < hdev->discovery.rssi)
7394 return false;
7395 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007396
7397 return true;
7398}
7399
Marcel Holtmann901801b2013-10-06 23:55:51 -07007400void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007401 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7402 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007403{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007404 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007405 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007406 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007407
Johan Hedberg75ce2082014-07-02 22:42:01 +03007408 /* Don't send events for a non-kernel initiated discovery. With
7409 * LE one exception is if we have pend_le_reports > 0 in which
7410 * case we're doing passive scanning and want these events.
7411 */
7412 if (!hci_discovery_active(hdev)) {
7413 if (link_type == ACL_LINK)
7414 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007415 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007416 return;
7417 }
Andre Guedes12602d02013-04-30 15:29:40 -03007418
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007419 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007420 /* We are using service discovery */
7421 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7422 scan_rsp_len))
7423 return;
7424 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007425
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007426 /* Make sure that the buffer is big enough. The 5 extra bytes
7427 * are for the potential CoD field.
7428 */
7429 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007430 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007431
Johan Hedberg1dc06092012-01-15 21:01:23 +02007432 memset(buf, 0, sizeof(buf));
7433
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007434 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7435 * RSSI value was reported as 0 when not available. This behavior
7436 * is kept when using device discovery. This is required for full
7437 * backwards compatibility with the API.
7438 *
7439 * However when using service discovery, the value 127 will be
7440 * returned when the RSSI is not available.
7441 */
Szymon Janc91200e92015-01-22 16:57:05 +01007442 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7443 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007444 rssi = 0;
7445
Johan Hedberg841c5642014-07-07 12:45:54 +03007446 bacpy(&ev->addr.bdaddr, bdaddr);
7447 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007448 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007449 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007450
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007451 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007452 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007453 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007454
Johan Hedberg1dc06092012-01-15 21:01:23 +02007455 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7456 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007457 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007458
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007459 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007460 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007461 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007462
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007463 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7464 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007465
Marcel Holtmann901801b2013-10-06 23:55:51 -07007466 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007467}
Johan Hedberga88a9652011-03-30 13:18:12 +03007468
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007469void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7470 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007471{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007472 struct mgmt_ev_device_found *ev;
7473 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7474 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007475
Johan Hedbergb644ba32012-01-17 21:48:47 +02007476 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007477
Johan Hedbergb644ba32012-01-17 21:48:47 +02007478 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007479
Johan Hedbergb644ba32012-01-17 21:48:47 +02007480 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007481 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007482 ev->rssi = rssi;
7483
7484 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007485 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007486
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007487 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007488
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007489 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007490}
Johan Hedberg314b2382011-04-27 10:29:57 -04007491
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007492void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007493{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007494 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007495
Andre Guedes343fb142011-11-22 17:14:19 -03007496 BT_DBG("%s discovering %u", hdev->name, discovering);
7497
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007498 memset(&ev, 0, sizeof(ev));
7499 ev.type = hdev->discovery.type;
7500 ev.discovering = discovering;
7501
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007502 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007503}
Antti Julku5e762442011-08-25 16:48:02 +03007504
Marcel Holtmann1904a852015-01-11 13:50:44 -08007505static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007506{
7507 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007508}
7509
7510void mgmt_reenable_advertising(struct hci_dev *hdev)
7511{
7512 struct hci_request req;
7513
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007514 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmann5976e602013-10-06 04:08:14 -07007515 return;
7516
7517 hci_req_init(&req, hdev);
7518 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007519 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007520}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007521
7522static struct hci_mgmt_chan chan = {
7523 .channel = HCI_CHANNEL_CONTROL,
7524 .handler_count = ARRAY_SIZE(mgmt_handlers),
7525 .handlers = mgmt_handlers,
7526};
7527
7528int mgmt_init(void)
7529{
7530 return hci_mgmt_chan_register(&chan);
7531}
7532
7533void mgmt_exit(void)
7534{
7535 hci_mgmt_chan_unregister(&chan);
7536}