blob: 600636c00d34817b59f5242874731bdc276574ef [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 Holtmann854bda12014-12-03 19:52:43 +010040#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020041
Johan Hedberge70bb2e2012-02-13 16:59:33 +020042static const u16 mgmt_commands[] = {
43 MGMT_OP_READ_INDEX_LIST,
44 MGMT_OP_READ_INFO,
45 MGMT_OP_SET_POWERED,
46 MGMT_OP_SET_DISCOVERABLE,
47 MGMT_OP_SET_CONNECTABLE,
48 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030049 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020050 MGMT_OP_SET_LINK_SECURITY,
51 MGMT_OP_SET_SSP,
52 MGMT_OP_SET_HS,
53 MGMT_OP_SET_LE,
54 MGMT_OP_SET_DEV_CLASS,
55 MGMT_OP_SET_LOCAL_NAME,
56 MGMT_OP_ADD_UUID,
57 MGMT_OP_REMOVE_UUID,
58 MGMT_OP_LOAD_LINK_KEYS,
59 MGMT_OP_LOAD_LONG_TERM_KEYS,
60 MGMT_OP_DISCONNECT,
61 MGMT_OP_GET_CONNECTIONS,
62 MGMT_OP_PIN_CODE_REPLY,
63 MGMT_OP_PIN_CODE_NEG_REPLY,
64 MGMT_OP_SET_IO_CAPABILITY,
65 MGMT_OP_PAIR_DEVICE,
66 MGMT_OP_CANCEL_PAIR_DEVICE,
67 MGMT_OP_UNPAIR_DEVICE,
68 MGMT_OP_USER_CONFIRM_REPLY,
69 MGMT_OP_USER_CONFIRM_NEG_REPLY,
70 MGMT_OP_USER_PASSKEY_REPLY,
71 MGMT_OP_USER_PASSKEY_NEG_REPLY,
72 MGMT_OP_READ_LOCAL_OOB_DATA,
73 MGMT_OP_ADD_REMOTE_OOB_DATA,
74 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
75 MGMT_OP_START_DISCOVERY,
76 MGMT_OP_STOP_DISCOVERY,
77 MGMT_OP_CONFIRM_NAME,
78 MGMT_OP_BLOCK_DEVICE,
79 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070080 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030081 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030082 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070083 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070084 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080085 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080086 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020087 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020088 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020089 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030090 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020091 MGMT_OP_ADD_DEVICE,
92 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030093 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020094 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020095 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020096 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020097 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010098 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020099};
100
101static const u16 mgmt_events[] = {
102 MGMT_EV_CONTROLLER_ERROR,
103 MGMT_EV_INDEX_ADDED,
104 MGMT_EV_INDEX_REMOVED,
105 MGMT_EV_NEW_SETTINGS,
106 MGMT_EV_CLASS_OF_DEV_CHANGED,
107 MGMT_EV_LOCAL_NAME_CHANGED,
108 MGMT_EV_NEW_LINK_KEY,
109 MGMT_EV_NEW_LONG_TERM_KEY,
110 MGMT_EV_DEVICE_CONNECTED,
111 MGMT_EV_DEVICE_DISCONNECTED,
112 MGMT_EV_CONNECT_FAILED,
113 MGMT_EV_PIN_CODE_REQUEST,
114 MGMT_EV_USER_CONFIRM_REQUEST,
115 MGMT_EV_USER_PASSKEY_REQUEST,
116 MGMT_EV_AUTH_FAILED,
117 MGMT_EV_DEVICE_FOUND,
118 MGMT_EV_DISCOVERING,
119 MGMT_EV_DEVICE_BLOCKED,
120 MGMT_EV_DEVICE_UNBLOCKED,
121 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300122 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800123 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700124 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200125 MGMT_EV_DEVICE_ADDED,
126 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300127 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200128 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200129 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200130 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200131};
132
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800133#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200134
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200135#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
136 "\x00\x00\x00\x00\x00\x00\x00\x00"
137
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200138struct mgmt_pending_cmd {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200140 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200141 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100142 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200143 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200144 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300145 void *user_data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200146 int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200147};
148
Johan Hedbergca69b792011-11-11 18:10:00 +0200149/* HCI to MGMT error code conversion table */
150static u8 mgmt_status_table[] = {
151 MGMT_STATUS_SUCCESS,
152 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
153 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
154 MGMT_STATUS_FAILED, /* Hardware Failure */
155 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
156 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200157 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200158 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
159 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
160 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
161 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
162 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
163 MGMT_STATUS_BUSY, /* Command Disallowed */
164 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
165 MGMT_STATUS_REJECTED, /* Rejected Security */
166 MGMT_STATUS_REJECTED, /* Rejected Personal */
167 MGMT_STATUS_TIMEOUT, /* Host Timeout */
168 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
169 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
170 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
171 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
172 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
173 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
174 MGMT_STATUS_BUSY, /* Repeated Attempts */
175 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
176 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
177 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
178 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
179 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
180 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
181 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
182 MGMT_STATUS_FAILED, /* Unspecified Error */
183 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
184 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
185 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
186 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
187 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
188 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
189 MGMT_STATUS_FAILED, /* Unit Link Key Used */
190 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
191 MGMT_STATUS_TIMEOUT, /* Instant Passed */
192 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
193 MGMT_STATUS_FAILED, /* Transaction Collision */
194 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
195 MGMT_STATUS_REJECTED, /* QoS Rejected */
196 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
197 MGMT_STATUS_REJECTED, /* Insufficient Security */
198 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
199 MGMT_STATUS_BUSY, /* Role Switch Pending */
200 MGMT_STATUS_FAILED, /* Slot Violation */
201 MGMT_STATUS_FAILED, /* Role Switch Failed */
202 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
203 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
204 MGMT_STATUS_BUSY, /* Host Busy Pairing */
205 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
206 MGMT_STATUS_BUSY, /* Controller Busy */
207 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
208 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
209 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
210 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
211 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
212};
213
214static u8 mgmt_status(u8 hci_status)
215{
216 if (hci_status < ARRAY_SIZE(mgmt_status_table))
217 return mgmt_status_table[hci_status];
218
219 return MGMT_STATUS_FAILED;
220}
221
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200222static int mgmt_send_event(u16 event, struct hci_dev *hdev,
223 unsigned short channel, void *data, u16 data_len,
224 struct sock *skip_sk)
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200225{
226 struct sk_buff *skb;
227 struct mgmt_hdr *hdr;
228
229 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
230 if (!skb)
231 return -ENOMEM;
232
233 hdr = (void *) skb_put(skb, sizeof(*hdr));
234 hdr->opcode = cpu_to_le16(event);
235 if (hdev)
236 hdr->index = cpu_to_le16(hdev->id);
237 else
238 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
239 hdr->len = cpu_to_le16(data_len);
240
241 if (data)
242 memcpy(skb_put(skb, data_len), data, data_len);
243
244 /* Time stamp */
245 __net_timestamp(skb);
246
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200247 hci_send_to_channel(channel, skb, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200248 kfree_skb(skb);
249
250 return 0;
251}
252
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200253static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
254 struct sock *skip_sk)
255{
256 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
257 skip_sk);
258}
259
Johan Hedberga69e8372015-03-06 21:08:53 +0200260static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200261{
262 struct sk_buff *skb;
263 struct mgmt_hdr *hdr;
264 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300265 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200266
Szymon Janc34eb5252011-02-28 14:10:08 +0100267 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200268
Andre Guedes790eff42012-06-07 19:05:46 -0300269 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200270 if (!skb)
271 return -ENOMEM;
272
273 hdr = (void *) skb_put(skb, sizeof(*hdr));
274
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100276 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200277 hdr->len = cpu_to_le16(sizeof(*ev));
278
279 ev = (void *) skb_put(skb, sizeof(*ev));
280 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200281 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200282
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 err = sock_queue_rcv_skb(sk, skb);
284 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200285 kfree_skb(skb);
286
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300287 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200288}
289
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200290static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
291 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200292{
293 struct sk_buff *skb;
294 struct mgmt_hdr *hdr;
295 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300296 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200297
298 BT_DBG("sock %p", sk);
299
Andre Guedes790eff42012-06-07 19:05:46 -0300300 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200301 if (!skb)
302 return -ENOMEM;
303
304 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200305
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700306 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100307 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200308 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200309
Johan Hedberga38528f2011-01-22 06:46:43 +0200310 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200311 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200312 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100313
314 if (rp)
315 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200316
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300317 err = sock_queue_rcv_skb(sk, skb);
318 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200319 kfree_skb(skb);
320
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100321 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200322}
323
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300324static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
325 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200326{
327 struct mgmt_rp_read_version rp;
328
329 BT_DBG("sock %p", sk);
330
331 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700332 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200333
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200334 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
335 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200336}
337
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300338static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
339 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200340{
341 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200342 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
343 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200344 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345 size_t rp_size;
346 int i, err;
347
348 BT_DBG("sock %p", sk);
349
350 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
351
352 rp = kmalloc(rp_size, GFP_KERNEL);
353 if (!rp)
354 return -ENOMEM;
355
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700356 rp->num_commands = cpu_to_le16(num_commands);
357 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200358
359 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
360 put_unaligned_le16(mgmt_commands[i], opcode);
361
362 for (i = 0; i < num_events; i++, opcode++)
363 put_unaligned_le16(mgmt_events[i], opcode);
364
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200365 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
366 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200367 kfree(rp);
368
369 return err;
370}
371
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300372static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
373 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200376 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200377 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200378 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300379 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200380
381 BT_DBG("sock %p", sk);
382
383 read_lock(&hci_dev_list_lock);
384
385 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300386 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200387 if (d->dev_type == HCI_BREDR &&
388 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700389 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200390 }
391
Johan Hedberga38528f2011-01-22 06:46:43 +0200392 rp_len = sizeof(*rp) + (2 * count);
393 rp = kmalloc(rp_len, GFP_ATOMIC);
394 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100395 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200396 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100397 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200398
Johan Hedberg476e44c2012-10-19 20:10:46 +0300399 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200400 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200401 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200402 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200403 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200404 continue;
405
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200406 /* Devices marked as raw-only are neither configured
407 * nor unconfigured controllers.
408 */
409 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700410 continue;
411
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200412 if (d->dev_type == HCI_BREDR &&
413 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700414 rp->index[count++] = cpu_to_le16(d->id);
415 BT_DBG("Added hci%u", d->id);
416 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417 }
418
Johan Hedberg476e44c2012-10-19 20:10:46 +0300419 rp->num_controllers = cpu_to_le16(count);
420 rp_len = sizeof(*rp) + (2 * count);
421
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200422 read_unlock(&hci_dev_list_lock);
423
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200424 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
425 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200426
Johan Hedberga38528f2011-01-22 06:46:43 +0200427 kfree(rp);
428
429 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200430}
431
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200432static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
433 void *data, u16 data_len)
434{
435 struct mgmt_rp_read_unconf_index_list *rp;
436 struct hci_dev *d;
437 size_t rp_len;
438 u16 count;
439 int err;
440
441 BT_DBG("sock %p", sk);
442
443 read_lock(&hci_dev_list_lock);
444
445 count = 0;
446 list_for_each_entry(d, &hci_dev_list, list) {
447 if (d->dev_type == HCI_BREDR &&
448 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
449 count++;
450 }
451
452 rp_len = sizeof(*rp) + (2 * count);
453 rp = kmalloc(rp_len, GFP_ATOMIC);
454 if (!rp) {
455 read_unlock(&hci_dev_list_lock);
456 return -ENOMEM;
457 }
458
459 count = 0;
460 list_for_each_entry(d, &hci_dev_list, list) {
461 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200462 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200463 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
464 continue;
465
466 /* Devices marked as raw-only are neither configured
467 * nor unconfigured controllers.
468 */
469 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
470 continue;
471
472 if (d->dev_type == HCI_BREDR &&
473 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
474 rp->index[count++] = cpu_to_le16(d->id);
475 BT_DBG("Added hci%u", d->id);
476 }
477 }
478
479 rp->num_controllers = cpu_to_le16(count);
480 rp_len = sizeof(*rp) + (2 * count);
481
482 read_unlock(&hci_dev_list_lock);
483
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200484 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
485 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200486
487 kfree(rp);
488
489 return err;
490}
491
Marcel Holtmanndbece372014-07-04 18:11:55 +0200492static bool is_configured(struct hci_dev *hdev)
493{
494 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
495 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
496 return false;
497
498 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
499 !bacmp(&hdev->public_addr, BDADDR_ANY))
500 return false;
501
502 return true;
503}
504
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200505static __le32 get_missing_options(struct hci_dev *hdev)
506{
507 u32 options = 0;
508
Marcel Holtmanndbece372014-07-04 18:11:55 +0200509 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
510 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200511 options |= MGMT_OPTION_EXTERNAL_CONFIG;
512
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200513 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
514 !bacmp(&hdev->public_addr, BDADDR_ANY))
515 options |= MGMT_OPTION_PUBLIC_ADDRESS;
516
517 return cpu_to_le32(options);
518}
519
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200520static int new_options(struct hci_dev *hdev, struct sock *skip)
521{
522 __le32 options = get_missing_options(hdev);
523
524 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
525 sizeof(options), skip);
526}
527
Marcel Holtmanndbece372014-07-04 18:11:55 +0200528static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
529{
530 __le32 options = get_missing_options(hdev);
531
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200532 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
533 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200534}
535
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200536static int read_config_info(struct sock *sk, struct hci_dev *hdev,
537 void *data, u16 data_len)
538{
539 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200541
542 BT_DBG("sock %p %s", sk, hdev->name);
543
544 hci_dev_lock(hdev);
545
546 memset(&rp, 0, sizeof(rp));
547 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200548
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200549 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
550 options |= MGMT_OPTION_EXTERNAL_CONFIG;
551
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200552 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200553 options |= MGMT_OPTION_PUBLIC_ADDRESS;
554
555 rp.supported_options = cpu_to_le32(options);
556 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200557
558 hci_dev_unlock(hdev);
559
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200560 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
561 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200562}
563
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200565{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200566 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200567
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200568 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300569 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800570 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300571 settings |= MGMT_SETTING_CONNECTABLE;
572 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200573
Andre Guedesed3fa312012-07-24 15:03:46 -0300574 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500575 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
576 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200577 settings |= MGMT_SETTING_BREDR;
578 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700579
580 if (lmp_ssp_capable(hdev)) {
581 settings |= MGMT_SETTING_SSP;
582 settings |= MGMT_SETTING_HS;
583 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800584
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800585 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800586 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700587 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100588
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300589 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200590 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300591 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300592 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200593 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800594 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300595 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200596
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200597 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
598 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200599 settings |= MGMT_SETTING_CONFIGURATION;
600
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200601 return settings;
602}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200603
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604static u32 get_current_settings(struct hci_dev *hdev)
605{
606 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200607
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200608 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100609 settings |= MGMT_SETTING_POWERED;
610
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200611 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200612 settings |= MGMT_SETTING_CONNECTABLE;
613
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500614 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
615 settings |= MGMT_SETTING_FAST_CONNECTABLE;
616
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200617 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_DISCOVERABLE;
619
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300620 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300621 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200622
Johan Hedberg56f87902013-10-02 13:43:13 +0300623 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200624 settings |= MGMT_SETTING_BREDR;
625
Johan Hedberg06199cf2012-02-22 16:37:11 +0200626 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200627 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200628
Johan Hedberg47990ea2012-02-22 11:58:37 +0200629 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200630 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200631
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200632 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200633 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200634
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200635 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
636 settings |= MGMT_SETTING_HS;
637
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200638 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300639 settings |= MGMT_SETTING_ADVERTISING;
640
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800641 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
642 settings |= MGMT_SETTING_SECURE_CONN;
643
Johan Hedberg0663b292014-06-24 13:15:50 +0300644 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800645 settings |= MGMT_SETTING_DEBUG_KEYS;
646
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200647 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
648 settings |= MGMT_SETTING_PRIVACY;
649
Marcel Holtmann93690c22015-03-06 10:11:21 -0800650 /* The current setting for static address has two purposes. The
651 * first is to indicate if the static address will be used and
652 * the second is to indicate if it is actually set.
653 *
654 * This means if the static address is not configured, this flag
655 * will never bet set. If the address is configured, then if the
656 * address is actually used decides if the flag is set or not.
657 *
658 * For single mode LE only controllers and dual-mode controllers
659 * with BR/EDR disabled, the existence of the static address will
660 * be evaluated.
661 */
662 if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ||
663 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
664 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
665 if (bacmp(&hdev->static_addr, BDADDR_ANY))
666 settings |= MGMT_SETTING_STATIC_ADDRESS;
667 }
668
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200669 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200670}
671
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300672#define PNP_INFO_SVCLASS_ID 0x1200
673
Johan Hedberg213202e2013-01-27 00:31:33 +0200674static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
675{
676 u8 *ptr = data, *uuids_start = NULL;
677 struct bt_uuid *uuid;
678
679 if (len < 4)
680 return ptr;
681
682 list_for_each_entry(uuid, &hdev->uuids, list) {
683 u16 uuid16;
684
685 if (uuid->size != 16)
686 continue;
687
688 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
689 if (uuid16 < 0x1100)
690 continue;
691
692 if (uuid16 == PNP_INFO_SVCLASS_ID)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID16_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u16) > len) {
704 uuids_start[1] = EIR_UUID16_SOME;
705 break;
706 }
707
708 *ptr++ = (uuid16 & 0x00ff);
709 *ptr++ = (uuid16 & 0xff00) >> 8;
710 uuids_start[0] += sizeof(uuid16);
711 }
712
713 return ptr;
714}
715
Johan Hedbergcdf19632013-01-27 00:31:34 +0200716static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 6)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 32)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID32_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + sizeof(u32) > len) {
737 uuids_start[1] = EIR_UUID32_SOME;
738 break;
739 }
740
741 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
742 ptr += sizeof(u32);
743 uuids_start[0] += sizeof(u32);
744 }
745
746 return ptr;
747}
748
Johan Hedbergc00d5752013-01-27 00:31:35 +0200749static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
750{
751 u8 *ptr = data, *uuids_start = NULL;
752 struct bt_uuid *uuid;
753
754 if (len < 18)
755 return ptr;
756
757 list_for_each_entry(uuid, &hdev->uuids, list) {
758 if (uuid->size != 128)
759 continue;
760
761 if (!uuids_start) {
762 uuids_start = ptr;
763 uuids_start[0] = 1;
764 uuids_start[1] = EIR_UUID128_ALL;
765 ptr += 2;
766 }
767
768 /* Stop if not enough space to put next UUID */
769 if ((ptr - data) + 16 > len) {
770 uuids_start[1] = EIR_UUID128_SOME;
771 break;
772 }
773
774 memcpy(ptr, uuid->uuid, 16);
775 ptr += 16;
776 uuids_start[0] += 16;
777 }
778
779 return ptr;
780}
781
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200782static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
783 struct hci_dev *hdev)
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300784{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200785 struct mgmt_pending_cmd *cmd;
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300786
787 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
788 if (cmd->opcode == opcode)
789 return cmd;
790 }
791
792 return NULL;
793}
794
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200795static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
796 struct hci_dev *hdev,
797 const void *data)
Johan Hedberg95868422014-06-28 17:54:07 +0300798{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200799 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +0300800
801 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
802 if (cmd->user_data != data)
803 continue;
804 if (cmd->opcode == opcode)
805 return cmd;
806 }
807
808 return NULL;
809}
810
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
812{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700813 u8 ad_len = 0;
814 size_t name_len;
815
816 name_len = strlen(hdev->dev_name);
817 if (name_len > 0) {
818 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
819
820 if (name_len > max_len) {
821 name_len = max_len;
822 ptr[1] = EIR_NAME_SHORT;
823 } else
824 ptr[1] = EIR_NAME_COMPLETE;
825
826 ptr[0] = name_len + 1;
827
828 memcpy(ptr + 2, hdev->dev_name, name_len);
829
830 ad_len += (name_len + 2);
831 ptr += (name_len + 2);
832 }
833
834 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700835}
836
837static void update_scan_rsp_data(struct hci_request *req)
838{
839 struct hci_dev *hdev = req->hdev;
840 struct hci_cp_le_set_scan_rsp_data cp;
841 u8 len;
842
Johan Hedberg7751ef12013-10-19 23:38:15 +0300843 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700844 return;
845
846 memset(&cp, 0, sizeof(cp));
847
848 len = create_scan_rsp_data(hdev, cp.data);
849
Johan Hedbergeb438b52013-10-16 15:31:07 +0300850 if (hdev->scan_rsp_data_len == len &&
851 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700852 return;
853
Johan Hedbergeb438b52013-10-16 15:31:07 +0300854 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
855 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700856
857 cp.length = len;
858
859 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
860}
861
Johan Hedberg9a43e252013-10-20 19:00:07 +0300862static u8 get_adv_discov_flags(struct hci_dev *hdev)
863{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200864 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300865
866 /* If there's a pending mgmt command the flags will not yet have
867 * their final values, so check for this first.
868 */
869 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
870 if (cmd) {
871 struct mgmt_mode *cp = cmd->param;
872 if (cp->val == 0x01)
873 return LE_AD_GENERAL;
874 else if (cp->val == 0x02)
875 return LE_AD_LIMITED;
876 } else {
877 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
878 return LE_AD_LIMITED;
879 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
880 return LE_AD_GENERAL;
881 }
882
883 return 0;
884}
885
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700886static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700887{
888 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700889
Johan Hedberg9a43e252013-10-20 19:00:07 +0300890 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891
Johan Hedberge8340042014-01-30 11:16:50 -0800892 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700893 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700894
895 if (flags) {
896 BT_DBG("adv flags 0x%02x", flags);
897
898 ptr[0] = 2;
899 ptr[1] = EIR_FLAGS;
900 ptr[2] = flags;
901
902 ad_len += 3;
903 ptr += 3;
904 }
905
906 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
907 ptr[0] = 2;
908 ptr[1] = EIR_TX_POWER;
909 ptr[2] = (u8) hdev->adv_tx_power;
910
911 ad_len += 3;
912 ptr += 3;
913 }
914
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700915 return ad_len;
916}
917
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700918static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700919{
920 struct hci_dev *hdev = req->hdev;
921 struct hci_cp_le_set_adv_data cp;
922 u8 len;
923
Johan Hedberg10994ce2013-10-19 23:38:16 +0300924 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700925 return;
926
927 memset(&cp, 0, sizeof(cp));
928
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700929 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700930
931 if (hdev->adv_data_len == len &&
932 memcmp(cp.data, hdev->adv_data, len) == 0)
933 return;
934
935 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
936 hdev->adv_data_len = len;
937
938 cp.length = len;
939
940 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
941}
942
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300943int mgmt_update_adv_data(struct hci_dev *hdev)
944{
945 struct hci_request req;
946
947 hci_req_init(&req, hdev);
948 update_adv_data(&req);
949
950 return hci_req_run(&req, NULL);
951}
952
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300953static void create_eir(struct hci_dev *hdev, u8 *data)
954{
955 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300956 size_t name_len;
957
958 name_len = strlen(hdev->dev_name);
959
960 if (name_len > 0) {
961 /* EIR Data type */
962 if (name_len > 48) {
963 name_len = 48;
964 ptr[1] = EIR_NAME_SHORT;
965 } else
966 ptr[1] = EIR_NAME_COMPLETE;
967
968 /* EIR Data length */
969 ptr[0] = name_len + 1;
970
971 memcpy(ptr + 2, hdev->dev_name, name_len);
972
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973 ptr += (name_len + 2);
974 }
975
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100976 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700977 ptr[0] = 2;
978 ptr[1] = EIR_TX_POWER;
979 ptr[2] = (u8) hdev->inq_tx_power;
980
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700981 ptr += 3;
982 }
983
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700984 if (hdev->devid_source > 0) {
985 ptr[0] = 9;
986 ptr[1] = EIR_DEVICE_ID;
987
988 put_unaligned_le16(hdev->devid_source, ptr + 2);
989 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
990 put_unaligned_le16(hdev->devid_product, ptr + 6);
991 put_unaligned_le16(hdev->devid_version, ptr + 8);
992
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700993 ptr += 10;
994 }
995
Johan Hedberg213202e2013-01-27 00:31:33 +0200996 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200997 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200998 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300999}
1000
Johan Hedberg890ea892013-03-15 17:06:52 -05001001static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001002{
Johan Hedberg890ea892013-03-15 17:06:52 -05001003 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001004 struct hci_cp_write_eir cp;
1005
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001006 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001007 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001008
Johan Hedberg976eb202012-10-24 21:12:01 +03001009 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001011
Johan Hedberg84bde9d2012-01-25 14:21:06 +02001012 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001013 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001014
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001015 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001017
1018 memset(&cp, 0, sizeof(cp));
1019
1020 create_eir(hdev, cp.data);
1021
1022 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001024
1025 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1026
Johan Hedberg890ea892013-03-15 17:06:52 -05001027 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001028}
1029
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030static u8 get_service_classes(struct hci_dev *hdev)
1031{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001032 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033 u8 val = 0;
1034
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001035 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001036 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001037
1038 return val;
1039}
1040
Johan Hedberg890ea892013-03-15 17:06:52 -05001041static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001042{
Johan Hedberg890ea892013-03-15 17:06:52 -05001043 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001044 u8 cod[3];
1045
1046 BT_DBG("%s", hdev->name);
1047
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001048 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001049 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001050
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001051 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1052 return;
1053
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001054 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001055 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001056
1057 cod[0] = hdev->minor_class;
1058 cod[1] = hdev->major_class;
1059 cod[2] = get_service_classes(hdev);
1060
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001061 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1062 cod[1] |= 0x20;
1063
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001064 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001065 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001066
Johan Hedberg890ea892013-03-15 17:06:52 -05001067 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001068}
1069
Johan Hedberga4858cb2014-02-25 19:56:31 +02001070static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001071{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001072 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001073
1074 /* If there's a pending mgmt command the flag will not yet have
1075 * it's final value, so check for this first.
1076 */
1077 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1078 if (cmd) {
1079 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001081 }
1082
Johan Hedberga4858cb2014-02-25 19:56:31 +02001083 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001084}
1085
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001086static void disable_advertising(struct hci_request *req)
1087{
1088 u8 enable = 0x00;
1089
1090 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1091}
1092
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001093static void enable_advertising(struct hci_request *req)
1094{
1095 struct hci_dev *hdev = req->hdev;
1096 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001097 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001098 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001099
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001100 if (hci_conn_num(hdev, LE_LINK) > 0)
1101 return;
1102
1103 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1104 disable_advertising(req);
1105
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001106 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001107 * hci_update_random_address knows that it's safe to go ahead
1108 * and write a new random address. The flag will be set back on
1109 * as soon as the SET_ADV_ENABLE HCI command completes.
1110 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001111 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001112
Johan Hedberga4858cb2014-02-25 19:56:31 +02001113 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001114
Johan Hedberga4858cb2014-02-25 19:56:31 +02001115 /* Set require_privacy to true only when non-connectable
1116 * advertising is used. In that case it is fine to use a
1117 * non-resolvable private address.
1118 */
1119 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001120 return;
1121
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001122 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001123 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1124 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001125 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001126 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001127 cp.channel_map = hdev->le_adv_channel_map;
1128
1129 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1130
1131 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1132}
1133
Johan Hedberg7d785252011-12-15 00:47:39 +02001134static void service_cache_off(struct work_struct *work)
1135{
1136 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001137 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001138 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001139
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001140 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001141 return;
1142
Johan Hedberg890ea892013-03-15 17:06:52 -05001143 hci_req_init(&req, hdev);
1144
Johan Hedberg7d785252011-12-15 00:47:39 +02001145 hci_dev_lock(hdev);
1146
Johan Hedberg890ea892013-03-15 17:06:52 -05001147 update_eir(&req);
1148 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001149
1150 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001151
1152 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001153}
1154
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001155static void rpa_expired(struct work_struct *work)
1156{
1157 struct hci_dev *hdev = container_of(work, struct hci_dev,
1158 rpa_expired.work);
1159 struct hci_request req;
1160
1161 BT_DBG("");
1162
1163 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1164
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001165 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001166 return;
1167
1168 /* The generation of a new RPA and programming it into the
1169 * controller happens in the enable_advertising() function.
1170 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001171 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001172 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001173 hci_req_run(&req, NULL);
1174}
1175
Johan Hedberg6a919082012-02-28 06:17:26 +02001176static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001177{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001178 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001179 return;
1180
Johan Hedberg4f87da82012-03-02 19:55:56 +02001181 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001182 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001183
Johan Hedberg4f87da82012-03-02 19:55:56 +02001184 /* Non-mgmt controlled devices get this bit set
1185 * implicitly so that pairing works for them, however
1186 * for mgmt we require user-space to explicitly enable
1187 * it
1188 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001189 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001190}
1191
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001192static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001193 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001194{
1195 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001196
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001197 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001198
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001199 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001200
Johan Hedberg03811012010-12-08 00:21:06 +02001201 memset(&rp, 0, sizeof(rp));
1202
Johan Hedberg03811012010-12-08 00:21:06 +02001203 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001204
1205 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001206 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001207
1208 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1209 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1210
1211 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001212
1213 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001214 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001215
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001216 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001217
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001218 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1219 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001220}
1221
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001222static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001223{
1224 sock_put(cmd->sk);
1225 kfree(cmd->param);
1226 kfree(cmd);
1227}
1228
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001229static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
1230 struct hci_dev *hdev,
1231 void *data, u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001232{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001233 struct mgmt_pending_cmd *cmd;
Johan Hedberg03811012010-12-08 00:21:06 +02001234
Johan Hedbergfca20012014-06-28 17:54:05 +03001235 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001236 if (!cmd)
1237 return NULL;
1238
1239 cmd->opcode = opcode;
1240 cmd->index = hdev->id;
1241
Johan Hedberg323b0b82014-12-05 13:36:01 +02001242 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001243 if (!cmd->param) {
1244 kfree(cmd);
1245 return NULL;
1246 }
1247
Johan Hedberg323b0b82014-12-05 13:36:01 +02001248 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001249
1250 cmd->sk = sk;
1251 sock_hold(sk);
1252
1253 list_add(&cmd->list, &hdev->mgmt_pending);
1254
1255 return cmd;
1256}
1257
1258static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001259 void (*cb)(struct mgmt_pending_cmd *cmd,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001260 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001261 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001262{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001263 struct mgmt_pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001264
Andre Guedesa3d09352013-02-01 11:21:30 -03001265 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001266 if (opcode > 0 && cmd->opcode != opcode)
1267 continue;
1268
1269 cb(cmd, data);
1270 }
1271}
1272
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001273static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001274{
1275 list_del(&cmd->list);
1276 mgmt_pending_free(cmd);
1277}
1278
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001279static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001280{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001281 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001282
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001283 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1284 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001285}
1286
Marcel Holtmann1904a852015-01-11 13:50:44 -08001287static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001288{
1289 BT_DBG("%s status 0x%02x", hdev->name, status);
1290
Johan Hedberga3172b72014-02-28 09:33:44 +02001291 if (hci_conn_count(hdev) == 0) {
1292 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001293 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001294 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001295}
1296
Johan Hedberg23a48092014-07-08 16:05:06 +03001297static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001298{
1299 struct hci_dev *hdev = req->hdev;
1300 struct hci_cp_remote_name_req_cancel cp;
1301 struct inquiry_entry *e;
1302
1303 switch (hdev->discovery.state) {
1304 case DISCOVERY_FINDING:
1305 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1306 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1307 } else {
1308 cancel_delayed_work(&hdev->le_scan_disable);
1309 hci_req_add_le_scan_disable(req);
1310 }
1311
Johan Hedberg23a48092014-07-08 16:05:06 +03001312 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001313
1314 case DISCOVERY_RESOLVING:
1315 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1316 NAME_PENDING);
1317 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001318 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001319
1320 bacpy(&cp.bdaddr, &e->data.bdaddr);
1321 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1322 &cp);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001325
1326 default:
1327 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001328 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001329 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001330 return true;
1331 }
1332
Johan Hedberg21a60d32014-06-10 14:05:58 +03001333 break;
1334 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001335
1336 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001337}
1338
Johan Hedberg8b064a32014-02-24 14:52:22 +02001339static int clean_up_hci_state(struct hci_dev *hdev)
1340{
1341 struct hci_request req;
1342 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001343 bool discov_stopped;
1344 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001345
1346 hci_req_init(&req, hdev);
1347
1348 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1349 test_bit(HCI_PSCAN, &hdev->flags)) {
1350 u8 scan = 0x00;
1351 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1352 }
1353
Johan Hedberg73e082f2014-07-08 15:07:51 +03001354 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001355 disable_advertising(&req);
1356
Johan Hedberg23a48092014-07-08 16:05:06 +03001357 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001358
1359 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1360 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001361 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001362
Johan Hedbergc9910d02014-02-27 14:35:12 +02001363 switch (conn->state) {
1364 case BT_CONNECTED:
1365 case BT_CONFIG:
1366 dc.handle = cpu_to_le16(conn->handle);
1367 dc.reason = 0x15; /* Terminated due to Power Off */
1368 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1369 break;
1370 case BT_CONNECT:
1371 if (conn->type == LE_LINK)
1372 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1373 0, NULL);
1374 else if (conn->type == ACL_LINK)
1375 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1376 6, &conn->dst);
1377 break;
1378 case BT_CONNECT2:
1379 bacpy(&rej.bdaddr, &conn->dst);
1380 rej.reason = 0x15; /* Terminated due to Power Off */
1381 if (conn->type == ACL_LINK)
1382 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1383 sizeof(rej), &rej);
1384 else if (conn->type == SCO_LINK)
1385 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1386 sizeof(rej), &rej);
1387 break;
1388 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001389 }
1390
Johan Hedberg23a48092014-07-08 16:05:06 +03001391 err = hci_req_run(&req, clean_up_hci_complete);
1392 if (!err && discov_stopped)
1393 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1394
1395 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001396}
1397
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001398static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001399 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001400{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001401 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001402 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001403 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001405 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001406
Johan Hedberga7e80f22013-01-09 16:05:19 +02001407 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001408 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1409 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001410
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001411 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001412
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001413 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001414 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1415 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001416 goto failed;
1417 }
1418
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001419 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1420 cancel_delayed_work(&hdev->power_off);
1421
1422 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001423 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1424 data, len);
1425 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001426 goto failed;
1427 }
1428 }
1429
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001430 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001431 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001432 goto failed;
1433 }
1434
Johan Hedberg03811012010-12-08 00:21:06 +02001435 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1436 if (!cmd) {
1437 err = -ENOMEM;
1438 goto failed;
1439 }
1440
Johan Hedberg8b064a32014-02-24 14:52:22 +02001441 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001442 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001443 err = 0;
1444 } else {
1445 /* Disconnect connections, stop scans, etc */
1446 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001447 if (!err)
1448 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1449 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001450
Johan Hedberg8b064a32014-02-24 14:52:22 +02001451 /* ENODATA means there were no HCI commands queued */
1452 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001453 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001454 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1455 err = 0;
1456 }
1457 }
Johan Hedberg03811012010-12-08 00:21:06 +02001458
1459failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001460 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001461 return err;
1462}
1463
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001464static int new_settings(struct hci_dev *hdev, struct sock *skip)
1465{
1466 __le32 ev;
1467
1468 ev = cpu_to_le32(get_current_settings(hdev));
1469
1470 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1471}
1472
Johan Hedberg91a668b2014-07-09 13:28:26 +03001473int mgmt_new_settings(struct hci_dev *hdev)
1474{
1475 return new_settings(hdev, NULL);
1476}
1477
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001478struct cmd_lookup {
1479 struct sock *sk;
1480 struct hci_dev *hdev;
1481 u8 mgmt_status;
1482};
1483
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001484static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001485{
1486 struct cmd_lookup *match = data;
1487
1488 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1489
1490 list_del(&cmd->list);
1491
1492 if (match->sk == NULL) {
1493 match->sk = cmd->sk;
1494 sock_hold(match->sk);
1495 }
1496
1497 mgmt_pending_free(cmd);
1498}
1499
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001500static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001501{
1502 u8 *status = data;
1503
Johan Hedberga69e8372015-03-06 21:08:53 +02001504 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001505 mgmt_pending_remove(cmd);
1506}
1507
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001508static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001509{
1510 if (cmd->cmd_complete) {
1511 u8 *status = data;
1512
1513 cmd->cmd_complete(cmd, *status);
1514 mgmt_pending_remove(cmd);
1515
1516 return;
1517 }
1518
1519 cmd_status_rsp(cmd, data);
1520}
1521
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001522static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001523{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001524 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1525 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001526}
1527
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001528static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001529{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001530 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1531 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001532}
1533
Johan Hedberge6fe7982013-10-02 15:45:22 +03001534static u8 mgmt_bredr_support(struct hci_dev *hdev)
1535{
1536 if (!lmp_bredr_capable(hdev))
1537 return MGMT_STATUS_NOT_SUPPORTED;
1538 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1539 return MGMT_STATUS_REJECTED;
1540 else
1541 return MGMT_STATUS_SUCCESS;
1542}
1543
1544static u8 mgmt_le_support(struct hci_dev *hdev)
1545{
1546 if (!lmp_le_capable(hdev))
1547 return MGMT_STATUS_NOT_SUPPORTED;
1548 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1549 return MGMT_STATUS_REJECTED;
1550 else
1551 return MGMT_STATUS_SUCCESS;
1552}
1553
Marcel Holtmann1904a852015-01-11 13:50:44 -08001554static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1555 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001556{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001557 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001558 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001559 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001560 bool changed;
1561
1562 BT_DBG("status 0x%02x", status);
1563
1564 hci_dev_lock(hdev);
1565
1566 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1567 if (!cmd)
1568 goto unlock;
1569
1570 if (status) {
1571 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001572 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001573 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001574 goto remove_cmd;
1575 }
1576
1577 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001578 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001579 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1580 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001581
1582 if (hdev->discov_timeout > 0) {
1583 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1584 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1585 to);
1586 }
1587 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001588 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1589 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001590 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001591
1592 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1593
1594 if (changed)
1595 new_settings(hdev, cmd->sk);
1596
Marcel Holtmann970ba522013-10-15 06:33:57 -07001597 /* When the discoverable mode gets changed, make sure
1598 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001599 * bit correctly set. Also update page scan based on whitelist
1600 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001601 */
1602 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001603 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001604 update_class(&req);
1605 hci_req_run(&req, NULL);
1606
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001607remove_cmd:
1608 mgmt_pending_remove(cmd);
1609
1610unlock:
1611 hci_dev_unlock(hdev);
1612}
1613
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001614static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001615 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001616{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001617 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001618 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001619 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001620 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001621 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001622 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001623
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001624 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001625
Johan Hedberg9a43e252013-10-20 19:00:07 +03001626 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1627 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02001628 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1629 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001630
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001631 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001632 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1633 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001634
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001635 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001636
1637 /* Disabling discoverable requires that no timeout is set,
1638 * and enabling limited discoverable requires a timeout.
1639 */
1640 if ((cp->val == 0x00 && timeout > 0) ||
1641 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001642 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1643 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001644
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001645 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001646
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001647 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001648 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1649 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001650 goto failed;
1651 }
1652
1653 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001654 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001655 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1656 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001657 goto failed;
1658 }
1659
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001660 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001661 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1662 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001663 goto failed;
1664 }
1665
1666 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001667 bool changed = false;
1668
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001669 /* Setting limited discoverable when powered off is
1670 * not a valid operation since it requires a timeout
1671 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1672 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001673 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1674 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1675 changed = true;
1676 }
1677
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001678 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001679 if (err < 0)
1680 goto failed;
1681
1682 if (changed)
1683 err = new_settings(hdev, sk);
1684
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001685 goto failed;
1686 }
1687
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001688 /* If the current mode is the same, then just update the timeout
1689 * value with the new value. And if only the timeout gets updated,
1690 * then no need for any HCI transactions.
1691 */
1692 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1693 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1694 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001695 cancel_delayed_work(&hdev->discov_off);
1696 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001697
Marcel Holtmann36261542013-10-15 08:28:51 -07001698 if (cp->val && hdev->discov_timeout > 0) {
1699 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001700 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001701 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001702 }
1703
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001704 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001705 goto failed;
1706 }
1707
1708 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1709 if (!cmd) {
1710 err = -ENOMEM;
1711 goto failed;
1712 }
1713
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001714 /* Cancel any potential discoverable timeout that might be
1715 * still active and store new timeout value. The arming of
1716 * the timeout happens in the complete handler.
1717 */
1718 cancel_delayed_work(&hdev->discov_off);
1719 hdev->discov_timeout = timeout;
1720
Johan Hedbergb456f872013-10-19 23:38:22 +03001721 /* Limited discoverable mode */
1722 if (cp->val == 0x02)
1723 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1724 else
1725 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1726
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001727 hci_req_init(&req, hdev);
1728
Johan Hedberg9a43e252013-10-20 19:00:07 +03001729 /* The procedure for LE-only controllers is much simpler - just
1730 * update the advertising data.
1731 */
1732 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1733 goto update_ad;
1734
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001735 scan = SCAN_PAGE;
1736
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001737 if (cp->val) {
1738 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001739
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001740 if (cp->val == 0x02) {
1741 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001742 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001743 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1744 hci_cp.iac_lap[1] = 0x8b;
1745 hci_cp.iac_lap[2] = 0x9e;
1746 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1747 hci_cp.iac_lap[4] = 0x8b;
1748 hci_cp.iac_lap[5] = 0x9e;
1749 } else {
1750 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001751 hci_cp.num_iac = 1;
1752 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1753 hci_cp.iac_lap[1] = 0x8b;
1754 hci_cp.iac_lap[2] = 0x9e;
1755 }
1756
1757 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1758 (hci_cp.num_iac * 3) + 1, &hci_cp);
1759
1760 scan |= SCAN_INQUIRY;
1761 } else {
1762 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1763 }
1764
1765 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001766
Johan Hedberg9a43e252013-10-20 19:00:07 +03001767update_ad:
1768 update_adv_data(&req);
1769
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001770 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001771 if (err < 0)
1772 mgmt_pending_remove(cmd);
1773
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001774failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001775 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001776 return err;
1777}
1778
Johan Hedberg406d7802013-03-15 17:07:09 -05001779static void write_fast_connectable(struct hci_request *req, bool enable)
1780{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001781 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001782 struct hci_cp_write_page_scan_activity acp;
1783 u8 type;
1784
Johan Hedberg547003b2013-10-21 16:51:53 +03001785 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1786 return;
1787
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001788 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1789 return;
1790
Johan Hedberg406d7802013-03-15 17:07:09 -05001791 if (enable) {
1792 type = PAGE_SCAN_TYPE_INTERLACED;
1793
1794 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001795 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001796 } else {
1797 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1798
1799 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001800 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001801 }
1802
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001803 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001804
Johan Hedbergbd98b992013-03-15 17:07:13 -05001805 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1806 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1807 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1808 sizeof(acp), &acp);
1809
1810 if (hdev->page_scan_type != type)
1811 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001812}
1813
Marcel Holtmann1904a852015-01-11 13:50:44 -08001814static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1815 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001816{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001817 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001818 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001819 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001820
1821 BT_DBG("status 0x%02x", status);
1822
1823 hci_dev_lock(hdev);
1824
1825 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1826 if (!cmd)
1827 goto unlock;
1828
Johan Hedberg37438c12013-10-14 16:20:05 +03001829 if (status) {
1830 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001831 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001832 goto remove_cmd;
1833 }
1834
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001835 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001836 if (cp->val) {
1837 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1838 &hdev->dev_flags);
1839 discov_changed = false;
1840 } else {
1841 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1842 &hdev->dev_flags);
1843 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1844 &hdev->dev_flags);
1845 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001846
Johan Hedberg2b76f452013-03-15 17:07:04 -05001847 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1848
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001849 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001850 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001851 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001852 if (discov_changed)
1853 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001854 hci_update_background_scan(hdev);
1855 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001856
Johan Hedberg37438c12013-10-14 16:20:05 +03001857remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001858 mgmt_pending_remove(cmd);
1859
1860unlock:
1861 hci_dev_unlock(hdev);
1862}
1863
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001864static int set_connectable_update_settings(struct hci_dev *hdev,
1865 struct sock *sk, u8 val)
1866{
1867 bool changed = false;
1868 int err;
1869
1870 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1871 changed = true;
1872
1873 if (val) {
1874 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1875 } else {
1876 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1877 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1878 }
1879
1880 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1881 if (err < 0)
1882 return err;
1883
Johan Hedberg562064e2014-07-08 16:35:34 +03001884 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001885 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001886 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001887 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001888 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001889
1890 return 0;
1891}
1892
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001893static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001894 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001895{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001896 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001897 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001899 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001900 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001901
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001902 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001903
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001904 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1905 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02001906 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1907 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001908
Johan Hedberga7e80f22013-01-09 16:05:19 +02001909 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001910 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1911 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001912
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001913 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001914
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001915 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001916 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001917 goto failed;
1918 }
1919
1920 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001921 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001922 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1923 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001924 goto failed;
1925 }
1926
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001927 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1928 if (!cmd) {
1929 err = -ENOMEM;
1930 goto failed;
1931 }
1932
Johan Hedberg2b76f452013-03-15 17:07:04 -05001933 hci_req_init(&req, hdev);
1934
Johan Hedberg9a43e252013-10-20 19:00:07 +03001935 /* If BR/EDR is not enabled and we disable advertising as a
1936 * by-product of disabling connectable, we need to update the
1937 * advertising flags.
1938 */
1939 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1940 if (!cp->val) {
1941 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1942 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1943 }
1944 update_adv_data(&req);
1945 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001946 if (cp->val) {
1947 scan = SCAN_PAGE;
1948 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001949 /* If we don't have any whitelist entries just
1950 * disable all scanning. If there are entries
1951 * and we had both page and inquiry scanning
1952 * enabled then fall back to only page scanning.
1953 * Otherwise no changes are needed.
1954 */
1955 if (list_empty(&hdev->whitelist))
1956 scan = SCAN_DISABLED;
1957 else if (test_bit(HCI_ISCAN, &hdev->flags))
1958 scan = SCAN_PAGE;
1959 else
1960 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001961
1962 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001963 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001964 cancel_delayed_work(&hdev->discov_off);
1965 }
1966
1967 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1968 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001969
Johan Hedberg3bd27242014-07-28 20:53:58 +03001970no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03001971 /* Update the advertising parameters if necessary */
1972 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001973 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001974
Johan Hedberg2b76f452013-03-15 17:07:04 -05001975 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001976 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001978 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001979 err = set_connectable_update_settings(hdev, sk,
1980 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001981 goto failed;
1982 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001983
1984failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001985 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986 return err;
1987}
1988
Johan Hedbergb2939472014-07-30 09:22:23 +03001989static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001990 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001991{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001992 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001993 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001994 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001996 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001997
Johan Hedberga7e80f22013-01-09 16:05:19 +02001998 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001999 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2000 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002001
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002002 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002003
2004 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002005 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002006 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002007 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002008
Johan Hedbergb2939472014-07-30 09:22:23 +03002009 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002010 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002011 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002012
Marcel Holtmann55594352013-10-06 16:11:57 -07002013 if (changed)
2014 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002015
Marcel Holtmann55594352013-10-06 16:11:57 -07002016unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002017 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002018 return err;
2019}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002020
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002021static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2022 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002023{
2024 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002025 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002026 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002027 int err;
2028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002029 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002030
Johan Hedberge6fe7982013-10-02 15:45:22 +03002031 status = mgmt_bredr_support(hdev);
2032 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002033 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2034 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002035
Johan Hedberga7e80f22013-01-09 16:05:19 +02002036 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002037 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2038 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002039
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002040 hci_dev_lock(hdev);
2041
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002042 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002043 bool changed = false;
2044
2045 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002046 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002047 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2048 changed = true;
2049 }
2050
2051 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2052 if (err < 0)
2053 goto failed;
2054
2055 if (changed)
2056 err = new_settings(hdev, sk);
2057
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002058 goto failed;
2059 }
2060
2061 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002062 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2063 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002064 goto failed;
2065 }
2066
2067 val = !!cp->val;
2068
2069 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2070 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2071 goto failed;
2072 }
2073
2074 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2075 if (!cmd) {
2076 err = -ENOMEM;
2077 goto failed;
2078 }
2079
2080 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2081 if (err < 0) {
2082 mgmt_pending_remove(cmd);
2083 goto failed;
2084 }
2085
2086failed:
2087 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002088 return err;
2089}
2090
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002091static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002092{
2093 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002094 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002095 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002096 int err;
2097
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002098 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002099
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002100 status = mgmt_bredr_support(hdev);
2101 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002102 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002103
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002104 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002105 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2106 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002107
Johan Hedberga7e80f22013-01-09 16:05:19 +02002108 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002109 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2110 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002111
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002112 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002113
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002114 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002115 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002116
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002117 if (cp->val) {
2118 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2119 &hdev->dev_flags);
2120 } else {
2121 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2122 &hdev->dev_flags);
2123 if (!changed)
2124 changed = test_and_clear_bit(HCI_HS_ENABLED,
2125 &hdev->dev_flags);
2126 else
2127 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002128 }
2129
2130 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2131 if (err < 0)
2132 goto failed;
2133
2134 if (changed)
2135 err = new_settings(hdev, sk);
2136
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 goto failed;
2138 }
2139
Johan Hedberg94d52da2015-02-19 17:38:06 +02002140 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002141 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2142 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002143 goto failed;
2144 }
2145
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002146 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002147 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2148 goto failed;
2149 }
2150
2151 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2152 if (!cmd) {
2153 err = -ENOMEM;
2154 goto failed;
2155 }
2156
Johan Hedberg37699722014-06-24 14:00:27 +03002157 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2158 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2159 sizeof(cp->val), &cp->val);
2160
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002161 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002162 if (err < 0) {
2163 mgmt_pending_remove(cmd);
2164 goto failed;
2165 }
2166
2167failed:
2168 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002169 return err;
2170}
2171
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002172static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173{
2174 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002176 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002177 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002179 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002180
Johan Hedberge6fe7982013-10-02 15:45:22 +03002181 status = mgmt_bredr_support(hdev);
2182 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002183 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002184
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002185 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002186 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2187 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002188
2189 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002190 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2191 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002192
Johan Hedberga7e80f22013-01-09 16:05:19 +02002193 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002194 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2195 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002196
Marcel Holtmannee392692013-10-01 22:59:23 -07002197 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002198
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002199 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002200 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2201 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002202 goto unlock;
2203 }
2204
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002205 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002206 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002207 } else {
2208 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002209 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2210 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002211 goto unlock;
2212 }
2213
Marcel Holtmannee392692013-10-01 22:59:23 -07002214 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002215 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002216
2217 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2218 if (err < 0)
2219 goto unlock;
2220
2221 if (changed)
2222 err = new_settings(hdev, sk);
2223
2224unlock:
2225 hci_dev_unlock(hdev);
2226 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002227}
2228
Marcel Holtmann1904a852015-01-11 13:50:44 -08002229static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002230{
2231 struct cmd_lookup match = { NULL, hdev };
2232
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302233 hci_dev_lock(hdev);
2234
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002235 if (status) {
2236 u8 mgmt_err = mgmt_status(status);
2237
2238 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2239 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302240 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002241 }
2242
2243 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2244
2245 new_settings(hdev, match.sk);
2246
2247 if (match.sk)
2248 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002249
2250 /* Make sure the controller has a good default for
2251 * advertising data. Restrict the update to when LE
2252 * has actually been enabled. During power on, the
2253 * update in powered_update_hci will take care of it.
2254 */
2255 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2256 struct hci_request req;
2257
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002258 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002259 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002260 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002261 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002262 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002263 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302264
2265unlock:
2266 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002267}
2268
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002269static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002270{
2271 struct mgmt_mode *cp = data;
2272 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002273 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002274 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002275 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002276 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002277
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002278 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002279
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002280 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002281 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2282 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002283
Johan Hedberga7e80f22013-01-09 16:05:19 +02002284 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002285 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2286 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002287
Johan Hedbergc73eee92013-04-19 18:35:21 +03002288 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002289 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002290 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2291 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002292
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002293 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002294
2295 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002296 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002297
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002298 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299 bool changed = false;
2300
2301 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2302 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2303 changed = true;
2304 }
2305
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002306 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2307 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002308 changed = true;
2309 }
2310
Johan Hedberg06199cf2012-02-22 16:37:11 +02002311 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2312 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002313 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002314
2315 if (changed)
2316 err = new_settings(hdev, sk);
2317
Johan Hedberg1de028c2012-02-29 19:55:35 -08002318 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002319 }
2320
Johan Hedberg4375f102013-09-25 13:26:10 +03002321 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2322 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002323 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2324 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002325 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002326 }
2327
2328 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2329 if (!cmd) {
2330 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002331 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002332 }
2333
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002334 hci_req_init(&req, hdev);
2335
Johan Hedberg06199cf2012-02-22 16:37:11 +02002336 memset(&hci_cp, 0, sizeof(hci_cp));
2337
2338 if (val) {
2339 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002340 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002341 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002342 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002343 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002344 }
2345
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002346 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2347 &hci_cp);
2348
2349 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302350 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002351 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002352
Johan Hedberg1de028c2012-02-29 19:55:35 -08002353unlock:
2354 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002355 return err;
2356}
2357
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002358/* This is a helper function to test for pending mgmt commands that can
2359 * cause CoD or EIR HCI commands. We can only allow one such pending
2360 * mgmt command at a time since otherwise we cannot easily track what
2361 * the current values are, will be, and based on that calculate if a new
2362 * HCI command needs to be sent and if yes with what value.
2363 */
2364static bool pending_eir_or_class(struct hci_dev *hdev)
2365{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002366 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002367
2368 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2369 switch (cmd->opcode) {
2370 case MGMT_OP_ADD_UUID:
2371 case MGMT_OP_REMOVE_UUID:
2372 case MGMT_OP_SET_DEV_CLASS:
2373 case MGMT_OP_SET_POWERED:
2374 return true;
2375 }
2376 }
2377
2378 return false;
2379}
2380
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002381static const u8 bluetooth_base_uuid[] = {
2382 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2383 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2384};
2385
2386static u8 get_uuid_size(const u8 *uuid)
2387{
2388 u32 val;
2389
2390 if (memcmp(uuid, bluetooth_base_uuid, 12))
2391 return 128;
2392
2393 val = get_unaligned_le32(&uuid[12]);
2394 if (val > 0xffff)
2395 return 32;
2396
2397 return 16;
2398}
2399
Johan Hedberg92da6092013-03-15 17:06:55 -05002400static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2401{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002402 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002403
2404 hci_dev_lock(hdev);
2405
2406 cmd = mgmt_pending_find(mgmt_op, hdev);
2407 if (!cmd)
2408 goto unlock;
2409
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002410 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2411 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002412
2413 mgmt_pending_remove(cmd);
2414
2415unlock:
2416 hci_dev_unlock(hdev);
2417}
2418
Marcel Holtmann1904a852015-01-11 13:50:44 -08002419static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002420{
2421 BT_DBG("status 0x%02x", status);
2422
2423 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2424}
2425
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002426static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002427{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002428 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002429 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002430 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002431 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002432 int err;
2433
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002434 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002435
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002436 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002437
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002438 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002439 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2440 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002441 goto failed;
2442 }
2443
Andre Guedes92c4c202012-06-07 19:05:44 -03002444 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002445 if (!uuid) {
2446 err = -ENOMEM;
2447 goto failed;
2448 }
2449
2450 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002451 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002452 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002453
Johan Hedbergde66aa62013-01-27 00:31:27 +02002454 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002455
Johan Hedberg890ea892013-03-15 17:06:52 -05002456 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002457
Johan Hedberg890ea892013-03-15 17:06:52 -05002458 update_class(&req);
2459 update_eir(&req);
2460
Johan Hedberg92da6092013-03-15 17:06:55 -05002461 err = hci_req_run(&req, add_uuid_complete);
2462 if (err < 0) {
2463 if (err != -ENODATA)
2464 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002465
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002466 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2467 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002468 goto failed;
2469 }
2470
2471 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002472 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002473 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002474 goto failed;
2475 }
2476
2477 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002478
2479failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002480 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481 return err;
2482}
2483
Johan Hedberg24b78d02012-02-23 23:24:30 +02002484static bool enable_service_cache(struct hci_dev *hdev)
2485{
2486 if (!hdev_is_powered(hdev))
2487 return false;
2488
2489 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002490 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2491 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002492 return true;
2493 }
2494
2495 return false;
2496}
2497
Marcel Holtmann1904a852015-01-11 13:50:44 -08002498static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002499{
2500 BT_DBG("status 0x%02x", status);
2501
2502 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2503}
2504
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002505static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002506 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002507{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002508 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002509 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002510 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002511 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 -05002512 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002513 int err, found;
2514
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002515 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002516
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002517 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002518
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002519 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002520 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2521 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002522 goto unlock;
2523 }
2524
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002525 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002526 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002527
Johan Hedberg24b78d02012-02-23 23:24:30 +02002528 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002529 err = mgmt_cmd_complete(sk, hdev->id,
2530 MGMT_OP_REMOVE_UUID,
2531 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002532 goto unlock;
2533 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002534
Johan Hedberg9246a862012-02-23 21:33:16 +02002535 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002536 }
2537
2538 found = 0;
2539
Johan Hedberg056341c2013-01-27 00:31:30 +02002540 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002541 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2542 continue;
2543
2544 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002545 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546 found++;
2547 }
2548
2549 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002550 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2551 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002552 goto unlock;
2553 }
2554
Johan Hedberg9246a862012-02-23 21:33:16 +02002555update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002556 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002557
Johan Hedberg890ea892013-03-15 17:06:52 -05002558 update_class(&req);
2559 update_eir(&req);
2560
Johan Hedberg92da6092013-03-15 17:06:55 -05002561 err = hci_req_run(&req, remove_uuid_complete);
2562 if (err < 0) {
2563 if (err != -ENODATA)
2564 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002565
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002566 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2567 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002568 goto unlock;
2569 }
2570
2571 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002572 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002573 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002574 goto unlock;
2575 }
2576
2577 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002578
2579unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002580 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002581 return err;
2582}
2583
Marcel Holtmann1904a852015-01-11 13:50:44 -08002584static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002585{
2586 BT_DBG("status 0x%02x", status);
2587
2588 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2589}
2590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002591static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002592 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002593{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002594 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002595 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002596 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002597 int err;
2598
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002599 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002600
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002601 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002602 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2603 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002604
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002605 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002606
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002607 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002608 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2609 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002610 goto unlock;
2611 }
2612
2613 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002614 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2615 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002616 goto unlock;
2617 }
2618
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002619 hdev->major_class = cp->major;
2620 hdev->minor_class = cp->minor;
2621
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002622 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002623 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2624 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002625 goto unlock;
2626 }
2627
Johan Hedberg890ea892013-03-15 17:06:52 -05002628 hci_req_init(&req, hdev);
2629
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002630 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002631 hci_dev_unlock(hdev);
2632 cancel_delayed_work_sync(&hdev->service_cache);
2633 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002634 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002635 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002636
Johan Hedberg890ea892013-03-15 17:06:52 -05002637 update_class(&req);
2638
Johan Hedberg92da6092013-03-15 17:06:55 -05002639 err = hci_req_run(&req, set_class_complete);
2640 if (err < 0) {
2641 if (err != -ENODATA)
2642 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002643
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002644 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2645 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002646 goto unlock;
2647 }
2648
2649 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002650 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002651 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002652 goto unlock;
2653 }
2654
2655 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002656
Johan Hedbergb5235a62012-02-21 14:32:24 +02002657unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002658 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002659 return err;
2660}
2661
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002662static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002663 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002664{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002665 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002666 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2667 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002668 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002669 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002670 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002671
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002672 BT_DBG("request for %s", hdev->name);
2673
2674 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002675 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2676 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002677
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002678 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002679 if (key_count > max_key_count) {
2680 BT_ERR("load_link_keys: too big key_count value %u",
2681 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002682 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2683 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002684 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002685
Johan Hedberg86742e12011-11-07 23:13:38 +02002686 expected_len = sizeof(*cp) + key_count *
2687 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002688 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002689 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002690 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002691 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2692 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002693 }
2694
Johan Hedberg4ae14302013-01-20 14:27:13 +02002695 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002696 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2697 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002698
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002699 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002700 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002701
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002702 for (i = 0; i < key_count; i++) {
2703 struct mgmt_link_key_info *key = &cp->keys[i];
2704
Marcel Holtmann8e991132014-01-10 02:07:25 -08002705 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002706 return mgmt_cmd_status(sk, hdev->id,
2707 MGMT_OP_LOAD_LINK_KEYS,
2708 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002709 }
2710
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002711 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002712
2713 hci_link_keys_clear(hdev);
2714
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002715 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002716 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2717 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002718 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002719 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2720 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002721
2722 if (changed)
2723 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002724
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002725 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002726 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002727
Johan Hedberg58e92932014-06-24 14:00:26 +03002728 /* Always ignore debug keys and require a new pairing if
2729 * the user wants to use them.
2730 */
2731 if (key->type == HCI_LK_DEBUG_COMBINATION)
2732 continue;
2733
Johan Hedberg7652ff62014-06-24 13:15:49 +03002734 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2735 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002736 }
2737
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002738 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002739
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002740 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002741
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002742 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002743}
2744
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002745static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002746 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002747{
2748 struct mgmt_ev_device_unpaired ev;
2749
2750 bacpy(&ev.addr.bdaddr, bdaddr);
2751 ev.addr.type = addr_type;
2752
2753 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002754 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002755}
2756
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002757static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002758 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002759{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002760 struct mgmt_cp_unpair_device *cp = data;
2761 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002762 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002763 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002764 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002765 int err;
2766
Johan Hedberga8a1d192011-11-10 15:54:38 +02002767 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002768 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2769 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002770
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002771 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002772 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2773 MGMT_STATUS_INVALID_PARAMS,
2774 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002775
Johan Hedberg118da702013-01-20 14:27:20 +02002776 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002777 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2778 MGMT_STATUS_INVALID_PARAMS,
2779 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002780
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002781 hci_dev_lock(hdev);
2782
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002783 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002784 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2785 MGMT_STATUS_NOT_POWERED, &rp,
2786 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002787 goto unlock;
2788 }
2789
Johan Hedberge0b2b272014-02-18 17:14:31 +02002790 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002791 /* If disconnection is requested, then look up the
2792 * connection. If the remote device is connected, it
2793 * will be later used to terminate the link.
2794 *
2795 * Setting it to NULL explicitly will cause no
2796 * termination of the link.
2797 */
2798 if (cp->disconnect)
2799 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2800 &cp->addr.bdaddr);
2801 else
2802 conn = NULL;
2803
Johan Hedberg124f6e32012-02-09 13:50:12 +02002804 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002805 } else {
2806 u8 addr_type;
2807
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002808 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2809 &cp->addr.bdaddr);
2810 if (conn) {
2811 /* Defer clearing up the connection parameters
2812 * until closing to give a chance of keeping
2813 * them if a repairing happens.
2814 */
2815 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2816
2817 /* If disconnection is not requested, then
2818 * clear the connection variable so that the
2819 * link is not terminated.
2820 */
2821 if (!cp->disconnect)
2822 conn = NULL;
2823 }
2824
Johan Hedberge0b2b272014-02-18 17:14:31 +02002825 if (cp->addr.type == BDADDR_LE_PUBLIC)
2826 addr_type = ADDR_LE_DEV_PUBLIC;
2827 else
2828 addr_type = ADDR_LE_DEV_RANDOM;
2829
Johan Hedberga7ec7332014-02-18 17:14:35 +02002830 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2831
Johan Hedberge0b2b272014-02-18 17:14:31 +02002832 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2833 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002834
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002835 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002836 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2837 MGMT_STATUS_NOT_PAIRED, &rp,
2838 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002839 goto unlock;
2840 }
2841
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002842 /* If the connection variable is set, then termination of the
2843 * link is requested.
2844 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002845 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002846 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2847 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002848 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002849 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002850 }
2851
Johan Hedberg124f6e32012-02-09 13:50:12 +02002852 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002853 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002854 if (!cmd) {
2855 err = -ENOMEM;
2856 goto unlock;
2857 }
2858
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002859 cmd->cmd_complete = addr_cmd_complete;
2860
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002861 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002862 dc.reason = 0x13; /* Remote User Terminated Connection */
2863 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2864 if (err < 0)
2865 mgmt_pending_remove(cmd);
2866
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002867unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002868 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002869 return err;
2870}
2871
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002872static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002873 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002874{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002875 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002876 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002877 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002878 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002879 int err;
2880
2881 BT_DBG("");
2882
Johan Hedberg06a63b12013-01-20 14:27:21 +02002883 memset(&rp, 0, sizeof(rp));
2884 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2885 rp.addr.type = cp->addr.type;
2886
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002887 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002888 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2889 MGMT_STATUS_INVALID_PARAMS,
2890 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002891
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002892 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002893
2894 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002895 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2896 MGMT_STATUS_NOT_POWERED, &rp,
2897 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002898 goto failed;
2899 }
2900
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002901 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002902 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2903 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002904 goto failed;
2905 }
2906
Andre Guedes591f47f2012-04-24 21:02:49 -03002907 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002908 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2909 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002910 else
2911 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002912
Vishal Agarwalf9607272012-06-13 05:32:43 +05302913 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002914 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2915 MGMT_STATUS_NOT_CONNECTED, &rp,
2916 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002917 goto failed;
2918 }
2919
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002920 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002921 if (!cmd) {
2922 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002923 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002924 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002925
Johan Hedbergf5818c22014-12-05 13:36:02 +02002926 cmd->cmd_complete = generic_cmd_complete;
2927
Johan Hedberge3f2f922014-08-18 20:33:33 +03002928 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002929 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002930 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002931
2932failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002933 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002934 return err;
2935}
2936
Andre Guedes57c14772012-04-24 21:02:50 -03002937static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002938{
2939 switch (link_type) {
2940 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002941 switch (addr_type) {
2942 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002943 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002944
Johan Hedberg48264f02011-11-09 13:58:58 +02002945 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002946 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002947 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002948 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002949
Johan Hedberg4c659c32011-11-07 23:13:39 +02002950 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002951 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002952 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002953 }
2954}
2955
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002956static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2957 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002958{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002959 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002960 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002961 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002962 int err;
2963 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002964
2965 BT_DBG("");
2966
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002967 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002968
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002969 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002970 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2971 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002972 goto unlock;
2973 }
2974
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002975 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002976 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2977 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002978 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002979 }
2980
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002981 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002982 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002983 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002984 err = -ENOMEM;
2985 goto unlock;
2986 }
2987
Johan Hedberg2784eb42011-01-21 13:56:35 +02002988 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002989 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002990 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2991 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002992 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002993 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002994 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002995 continue;
2996 i++;
2997 }
2998
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002999 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003000
Johan Hedberg4c659c32011-11-07 23:13:39 +02003001 /* Recalculate length in case of filtered SCO connections, etc */
3002 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003003
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003004 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3005 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003006
Johan Hedberga38528f2011-01-22 06:46:43 +02003007 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003008
3009unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003010 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003011 return err;
3012}
3013
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003014static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003015 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003016{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003017 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003018 int err;
3019
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003020 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003021 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003022 if (!cmd)
3023 return -ENOMEM;
3024
Johan Hedbergd8457692012-02-17 14:24:57 +02003025 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003026 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003027 if (err < 0)
3028 mgmt_pending_remove(cmd);
3029
3030 return err;
3031}
3032
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003033static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003034 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003035{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003036 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003037 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003038 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003039 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040 int err;
3041
3042 BT_DBG("");
3043
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003044 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003045
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003046 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003047 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3048 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003049 goto failed;
3050 }
3051
Johan Hedbergd8457692012-02-17 14:24:57 +02003052 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003053 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003054 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3055 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003056 goto failed;
3057 }
3058
3059 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003060 struct mgmt_cp_pin_code_neg_reply ncp;
3061
3062 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003063
3064 BT_ERR("PIN code is not 16 bytes long");
3065
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003066 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003067 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003068 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3069 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003070
3071 goto failed;
3072 }
3073
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003074 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003075 if (!cmd) {
3076 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003077 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003078 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003079
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003080 cmd->cmd_complete = addr_cmd_complete;
3081
Johan Hedbergd8457692012-02-17 14:24:57 +02003082 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003083 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003084 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003085
3086 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3087 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003088 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003089
3090failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003091 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003092 return err;
3093}
3094
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003095static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3096 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003097{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003098 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003099
3100 BT_DBG("");
3101
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003102 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003103 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3104 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003105
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003106 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003107
3108 hdev->io_capability = cp->io_capability;
3109
3110 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003111 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003112
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003113 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003114
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003115 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3116 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003117}
3118
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003119static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003120{
3121 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003122 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003123
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003124 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003125 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3126 continue;
3127
Johan Hedberge9a416b2011-02-19 12:05:56 -03003128 if (cmd->user_data != conn)
3129 continue;
3130
3131 return cmd;
3132 }
3133
3134 return NULL;
3135}
3136
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003137static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003138{
3139 struct mgmt_rp_pair_device rp;
3140 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003141 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003142
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003143 bacpy(&rp.addr.bdaddr, &conn->dst);
3144 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003145
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003146 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3147 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148
3149 /* So we don't get further callbacks for this connection */
3150 conn->connect_cfm_cb = NULL;
3151 conn->security_cfm_cb = NULL;
3152 conn->disconn_cfm_cb = NULL;
3153
David Herrmann76a68ba2013-04-06 20:28:37 +02003154 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003155
3156 /* The device is paired so there is no need to remove
3157 * its connection parameters anymore.
3158 */
3159 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003160
3161 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003162
3163 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003164}
3165
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003166void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3167{
3168 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003169 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003170
3171 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003172 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003173 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003174 mgmt_pending_remove(cmd);
3175 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003176}
3177
Johan Hedberge9a416b2011-02-19 12:05:56 -03003178static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3179{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003180 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003181
3182 BT_DBG("status %u", status);
3183
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003184 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003185 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003186 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003187 return;
3188 }
3189
3190 cmd->cmd_complete(cmd, mgmt_status(status));
3191 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003192}
3193
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003194static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303195{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003196 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303197
3198 BT_DBG("status %u", status);
3199
3200 if (!status)
3201 return;
3202
3203 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003204 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303205 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003206 return;
3207 }
3208
3209 cmd->cmd_complete(cmd, mgmt_status(status));
3210 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303211}
3212
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003213static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003214 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003215{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003216 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003217 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003218 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003219 u8 sec_level, auth_type;
3220 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003221 int err;
3222
3223 BT_DBG("");
3224
Szymon Jancf950a30e2013-01-18 12:48:07 +01003225 memset(&rp, 0, sizeof(rp));
3226 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3227 rp.addr.type = cp->addr.type;
3228
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003229 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003230 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3231 MGMT_STATUS_INVALID_PARAMS,
3232 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003233
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003234 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003235 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3236 MGMT_STATUS_INVALID_PARAMS,
3237 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003238
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003239 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003240
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003241 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003242 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3243 MGMT_STATUS_NOT_POWERED, &rp,
3244 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003245 goto unlock;
3246 }
3247
Johan Hedberg55e76b32015-03-10 22:34:40 +02003248 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3249 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3250 MGMT_STATUS_ALREADY_PAIRED, &rp,
3251 sizeof(rp));
3252 goto unlock;
3253 }
3254
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003255 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003256 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003257
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003258 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003259 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3260 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003261 } else {
3262 u8 addr_type;
3263
3264 /* Convert from L2CAP channel address type to HCI address type
3265 */
3266 if (cp->addr.type == BDADDR_LE_PUBLIC)
3267 addr_type = ADDR_LE_DEV_PUBLIC;
3268 else
3269 addr_type = ADDR_LE_DEV_RANDOM;
3270
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003271 /* When pairing a new device, it is expected to remember
3272 * this device for future connections. Adding the connection
3273 * parameter information ahead of time allows tracking
3274 * of the slave preferred values and will speed up any
3275 * further connection establishment.
3276 *
3277 * If connection parameters already exist, then they
3278 * will be kept and this function does nothing.
3279 */
3280 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3281
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003282 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003283 sec_level, HCI_LE_CONN_TIMEOUT,
3284 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003285 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003286
Ville Tervo30e76272011-02-22 16:10:53 -03003287 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003288 int status;
3289
3290 if (PTR_ERR(conn) == -EBUSY)
3291 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003292 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3293 status = MGMT_STATUS_NOT_SUPPORTED;
3294 else if (PTR_ERR(conn) == -ECONNREFUSED)
3295 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003296 else
3297 status = MGMT_STATUS_CONNECT_FAILED;
3298
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003299 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3300 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003301 goto unlock;
3302 }
3303
3304 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003305 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003306 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3307 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003308 goto unlock;
3309 }
3310
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003311 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003312 if (!cmd) {
3313 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003314 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003315 goto unlock;
3316 }
3317
Johan Hedberg04ab2742014-12-05 13:36:04 +02003318 cmd->cmd_complete = pairing_complete;
3319
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003320 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003321 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003322 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003323 conn->security_cfm_cb = pairing_complete_cb;
3324 conn->disconn_cfm_cb = pairing_complete_cb;
3325 } else {
3326 conn->connect_cfm_cb = le_pairing_complete_cb;
3327 conn->security_cfm_cb = le_pairing_complete_cb;
3328 conn->disconn_cfm_cb = le_pairing_complete_cb;
3329 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003330
Johan Hedberge9a416b2011-02-19 12:05:56 -03003331 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003332 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003333
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003334 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003335 hci_conn_security(conn, sec_level, auth_type, true)) {
3336 cmd->cmd_complete(cmd, 0);
3337 mgmt_pending_remove(cmd);
3338 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003339
3340 err = 0;
3341
3342unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003343 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003344 return err;
3345}
3346
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003347static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3348 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003349{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003350 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003351 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003352 struct hci_conn *conn;
3353 int err;
3354
3355 BT_DBG("");
3356
Johan Hedberg28424702012-02-02 04:02:29 +02003357 hci_dev_lock(hdev);
3358
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003359 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003360 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3361 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003362 goto unlock;
3363 }
3364
Johan Hedberg28424702012-02-02 04:02:29 +02003365 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3366 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003367 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3368 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003369 goto unlock;
3370 }
3371
3372 conn = cmd->user_data;
3373
3374 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003375 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3376 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003377 goto unlock;
3378 }
3379
Johan Hedberga511b352014-12-11 21:45:45 +02003380 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3381 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003382
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003383 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3384 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003385unlock:
3386 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003387 return err;
3388}
3389
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003390static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003391 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003392 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003393{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003394 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003395 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003396 int err;
3397
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003398 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003399
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003400 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003401 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3402 MGMT_STATUS_NOT_POWERED, addr,
3403 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003404 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003405 }
3406
Johan Hedberg1707c602013-03-15 17:07:15 -05003407 if (addr->type == BDADDR_BREDR)
3408 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003409 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003410 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003411
Johan Hedberg272d90d2012-02-09 15:26:12 +02003412 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003413 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3414 MGMT_STATUS_NOT_CONNECTED, addr,
3415 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003416 goto done;
3417 }
3418
Johan Hedberg1707c602013-03-15 17:07:15 -05003419 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003420 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003421 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003422 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3423 MGMT_STATUS_SUCCESS, addr,
3424 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003425 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003426 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3427 MGMT_STATUS_FAILED, addr,
3428 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003429
Brian Gix47c15e22011-11-16 13:53:14 -08003430 goto done;
3431 }
3432
Johan Hedberg1707c602013-03-15 17:07:15 -05003433 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003434 if (!cmd) {
3435 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003436 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003437 }
3438
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003439 cmd->cmd_complete = addr_cmd_complete;
3440
Brian Gix0df4c182011-11-16 13:53:13 -08003441 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003442 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3443 struct hci_cp_user_passkey_reply cp;
3444
Johan Hedberg1707c602013-03-15 17:07:15 -05003445 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003446 cp.passkey = passkey;
3447 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3448 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003449 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3450 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003451
Johan Hedberga664b5b2011-02-19 12:06:02 -03003452 if (err < 0)
3453 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003454
Brian Gix0df4c182011-11-16 13:53:13 -08003455done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003456 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003457 return err;
3458}
3459
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303460static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3461 void *data, u16 len)
3462{
3463 struct mgmt_cp_pin_code_neg_reply *cp = data;
3464
3465 BT_DBG("");
3466
Johan Hedberg1707c602013-03-15 17:07:15 -05003467 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303468 MGMT_OP_PIN_CODE_NEG_REPLY,
3469 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3470}
3471
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003472static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3473 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003474{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003475 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003476
3477 BT_DBG("");
3478
3479 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003480 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3481 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003482
Johan Hedberg1707c602013-03-15 17:07:15 -05003483 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 MGMT_OP_USER_CONFIRM_REPLY,
3485 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003486}
3487
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003488static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003489 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003490{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003491 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003492
3493 BT_DBG("");
3494
Johan Hedberg1707c602013-03-15 17:07:15 -05003495 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003496 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3497 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003498}
3499
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003500static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3501 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003502{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003503 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003504
3505 BT_DBG("");
3506
Johan Hedberg1707c602013-03-15 17:07:15 -05003507 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003508 MGMT_OP_USER_PASSKEY_REPLY,
3509 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003510}
3511
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003512static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003513 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003514{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003515 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003516
3517 BT_DBG("");
3518
Johan Hedberg1707c602013-03-15 17:07:15 -05003519 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003520 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3521 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003522}
3523
Johan Hedberg13928972013-03-15 17:07:00 -05003524static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003525{
Johan Hedberg13928972013-03-15 17:07:00 -05003526 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003527 struct hci_cp_write_local_name cp;
3528
Johan Hedberg13928972013-03-15 17:07:00 -05003529 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003530
Johan Hedberg890ea892013-03-15 17:06:52 -05003531 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003532}
3533
Marcel Holtmann1904a852015-01-11 13:50:44 -08003534static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003535{
3536 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003537 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003538
3539 BT_DBG("status 0x%02x", status);
3540
3541 hci_dev_lock(hdev);
3542
3543 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3544 if (!cmd)
3545 goto unlock;
3546
3547 cp = cmd->param;
3548
3549 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003550 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3551 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003552 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003553 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3554 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003555
3556 mgmt_pending_remove(cmd);
3557
3558unlock:
3559 hci_dev_unlock(hdev);
3560}
3561
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003562static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003563 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003564{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003565 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003566 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003567 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003568 int err;
3569
3570 BT_DBG("");
3571
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003572 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003573
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003574 /* If the old values are the same as the new ones just return a
3575 * direct command complete event.
3576 */
3577 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3578 !memcmp(hdev->short_name, cp->short_name,
3579 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003580 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3581 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003582 goto failed;
3583 }
3584
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003585 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003586
Johan Hedbergb5235a62012-02-21 14:32:24 +02003587 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003588 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003589
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003590 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3591 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003592 if (err < 0)
3593 goto failed;
3594
3595 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003596 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003597
Johan Hedbergb5235a62012-02-21 14:32:24 +02003598 goto failed;
3599 }
3600
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003601 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003602 if (!cmd) {
3603 err = -ENOMEM;
3604 goto failed;
3605 }
3606
Johan Hedberg13928972013-03-15 17:07:00 -05003607 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3608
Johan Hedberg890ea892013-03-15 17:06:52 -05003609 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003610
3611 if (lmp_bredr_capable(hdev)) {
3612 update_name(&req);
3613 update_eir(&req);
3614 }
3615
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003616 /* The name is stored in the scan response data and so
3617 * no need to udpate the advertising data here.
3618 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003619 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003620 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003621
Johan Hedberg13928972013-03-15 17:07:00 -05003622 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003623 if (err < 0)
3624 mgmt_pending_remove(cmd);
3625
3626failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003627 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003628 return err;
3629}
3630
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003631static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003632 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003633{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003634 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003635 int err;
3636
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003637 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003638
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003639 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003640
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003641 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003642 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3643 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003644 goto unlock;
3645 }
3646
Andre Guedes9a1a1992012-07-24 15:03:48 -03003647 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003648 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3649 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003650 goto unlock;
3651 }
3652
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003653 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003654 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3655 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003656 goto unlock;
3657 }
3658
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003659 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003660 if (!cmd) {
3661 err = -ENOMEM;
3662 goto unlock;
3663 }
3664
Johan Hedberg710f11c2014-05-26 11:21:22 +03003665 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003666 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3667 0, NULL);
3668 else
3669 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3670
Szymon Jancc35938b2011-03-22 13:12:21 +01003671 if (err < 0)
3672 mgmt_pending_remove(cmd);
3673
3674unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003675 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003676 return err;
3677}
3678
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003679static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003680 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003681{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003682 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003683 int err;
3684
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003685 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003686
Johan Hedberg5d57e792015-01-23 10:10:38 +02003687 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003688 return mgmt_cmd_complete(sk, hdev->id,
3689 MGMT_OP_ADD_REMOTE_OOB_DATA,
3690 MGMT_STATUS_INVALID_PARAMS,
3691 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003692
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003693 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003694
Marcel Holtmannec109112014-01-10 02:07:30 -08003695 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3696 struct mgmt_cp_add_remote_oob_data *cp = data;
3697 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003698
Johan Hedbergc19a4952014-11-17 20:52:19 +02003699 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003700 err = mgmt_cmd_complete(sk, hdev->id,
3701 MGMT_OP_ADD_REMOTE_OOB_DATA,
3702 MGMT_STATUS_INVALID_PARAMS,
3703 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003704 goto unlock;
3705 }
3706
Marcel Holtmannec109112014-01-10 02:07:30 -08003707 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003708 cp->addr.type, cp->hash,
3709 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003710 if (err < 0)
3711 status = MGMT_STATUS_FAILED;
3712 else
3713 status = MGMT_STATUS_SUCCESS;
3714
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003715 err = mgmt_cmd_complete(sk, hdev->id,
3716 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3717 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003718 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3719 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003720 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003721 u8 status;
3722
Johan Hedberg86df9202014-10-26 20:52:27 +01003723 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003724 /* Enforce zero-valued 192-bit parameters as
3725 * long as legacy SMP OOB isn't implemented.
3726 */
3727 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3728 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003729 err = mgmt_cmd_complete(sk, hdev->id,
3730 MGMT_OP_ADD_REMOTE_OOB_DATA,
3731 MGMT_STATUS_INVALID_PARAMS,
3732 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003733 goto unlock;
3734 }
3735
Johan Hedberg86df9202014-10-26 20:52:27 +01003736 rand192 = NULL;
3737 hash192 = NULL;
3738 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003739 /* In case one of the P-192 values is set to zero,
3740 * then just disable OOB data for P-192.
3741 */
3742 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3743 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3744 rand192 = NULL;
3745 hash192 = NULL;
3746 } else {
3747 rand192 = cp->rand192;
3748 hash192 = cp->hash192;
3749 }
3750 }
3751
3752 /* In case one of the P-256 values is set to zero, then just
3753 * disable OOB data for P-256.
3754 */
3755 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3756 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3757 rand256 = NULL;
3758 hash256 = NULL;
3759 } else {
3760 rand256 = cp->rand256;
3761 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003762 }
3763
Johan Hedberg81328d52014-10-26 20:33:47 +01003764 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003765 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003766 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003767 if (err < 0)
3768 status = MGMT_STATUS_FAILED;
3769 else
3770 status = MGMT_STATUS_SUCCESS;
3771
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003772 err = mgmt_cmd_complete(sk, hdev->id,
3773 MGMT_OP_ADD_REMOTE_OOB_DATA,
3774 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003775 } else {
3776 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003777 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3778 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003779 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003780
Johan Hedbergc19a4952014-11-17 20:52:19 +02003781unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003782 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003783 return err;
3784}
3785
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003786static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003787 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003788{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003789 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003790 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003791 int err;
3792
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003793 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003794
Johan Hedbergc19a4952014-11-17 20:52:19 +02003795 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003796 return mgmt_cmd_complete(sk, hdev->id,
3797 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3798 MGMT_STATUS_INVALID_PARAMS,
3799 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003800
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003801 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003802
Johan Hedbergeedbd582014-11-15 09:34:23 +02003803 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3804 hci_remote_oob_data_clear(hdev);
3805 status = MGMT_STATUS_SUCCESS;
3806 goto done;
3807 }
3808
Johan Hedberg6928a922014-10-26 20:46:09 +01003809 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003810 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003811 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003812 else
Szymon Janca6785be2012-12-13 15:11:21 +01003813 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003814
Johan Hedbergeedbd582014-11-15 09:34:23 +02003815done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003816 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3817 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003818
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003819 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003820 return err;
3821}
3822
Marcel Holtmann80190442014-12-04 11:36:36 +01003823static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003824{
Marcel Holtmann80190442014-12-04 11:36:36 +01003825 struct hci_dev *hdev = req->hdev;
3826 struct hci_cp_le_set_scan_param param_cp;
3827 struct hci_cp_le_set_scan_enable enable_cp;
3828 struct hci_cp_inquiry inq_cp;
3829 /* General inquiry access code (GIAC) */
3830 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3831 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003832 int err;
3833
Marcel Holtmann80190442014-12-04 11:36:36 +01003834 switch (hdev->discovery.type) {
3835 case DISCOV_TYPE_BREDR:
3836 *status = mgmt_bredr_support(hdev);
3837 if (*status)
3838 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003839
Marcel Holtmann80190442014-12-04 11:36:36 +01003840 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3841 *status = MGMT_STATUS_BUSY;
3842 return false;
3843 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003844
Marcel Holtmann80190442014-12-04 11:36:36 +01003845 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003846
Marcel Holtmann80190442014-12-04 11:36:36 +01003847 memset(&inq_cp, 0, sizeof(inq_cp));
3848 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3849 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3850 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3851 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003852
Marcel Holtmann80190442014-12-04 11:36:36 +01003853 case DISCOV_TYPE_LE:
3854 case DISCOV_TYPE_INTERLEAVED:
3855 *status = mgmt_le_support(hdev);
3856 if (*status)
3857 return false;
3858
3859 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3860 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3861 *status = MGMT_STATUS_NOT_SUPPORTED;
3862 return false;
3863 }
3864
3865 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3866 /* Don't let discovery abort an outgoing
3867 * connection attempt that's using directed
3868 * advertising.
3869 */
3870 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3871 BT_CONNECT)) {
3872 *status = MGMT_STATUS_REJECTED;
3873 return false;
3874 }
3875
3876 disable_advertising(req);
3877 }
3878
3879 /* If controller is scanning, it means the background scanning
3880 * is running. Thus, we should temporarily stop it in order to
3881 * set the discovery scanning parameters.
3882 */
3883 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3884 hci_req_add_le_scan_disable(req);
3885
3886 memset(&param_cp, 0, sizeof(param_cp));
3887
3888 /* All active scans will be done with either a resolvable
3889 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003890 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003891 */
3892 err = hci_update_random_address(req, true, &own_addr_type);
3893 if (err < 0) {
3894 *status = MGMT_STATUS_FAILED;
3895 return false;
3896 }
3897
3898 param_cp.type = LE_SCAN_ACTIVE;
3899 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3900 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3901 param_cp.own_address_type = own_addr_type;
3902 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3903 &param_cp);
3904
3905 memset(&enable_cp, 0, sizeof(enable_cp));
3906 enable_cp.enable = LE_SCAN_ENABLE;
3907 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3908 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3909 &enable_cp);
3910 break;
3911
3912 default:
3913 *status = MGMT_STATUS_INVALID_PARAMS;
3914 return false;
3915 }
3916
3917 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003918}
3919
Marcel Holtmann1904a852015-01-11 13:50:44 -08003920static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3921 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003922{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003923 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003924 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003925
Andre Guedes7c307722013-04-30 15:29:28 -03003926 BT_DBG("status %d", status);
3927
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003928 hci_dev_lock(hdev);
3929
3930 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003931 if (!cmd)
3932 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3933
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003934 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003935 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003936 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003937 }
3938
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003939 if (status) {
3940 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3941 goto unlock;
3942 }
3943
Andre Guedes7c307722013-04-30 15:29:28 -03003944 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003945
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003946 /* If the scan involves LE scan, pick proper timeout to schedule
3947 * hdev->le_scan_disable that will stop it.
3948 */
Andre Guedes7c307722013-04-30 15:29:28 -03003949 switch (hdev->discovery.type) {
3950 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003951 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003952 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003953 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003954 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003955 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003956 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003957 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003958 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003959 default:
3960 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003961 timeout = 0;
3962 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003963 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003964
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003965 if (timeout) {
3966 /* When service discovery is used and the controller has
3967 * a strict duplicate filter, it is important to remember
3968 * the start and duration of the scan. This is required
3969 * for restarting scanning during the discovery phase.
3970 */
3971 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3972 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003973 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003974 hdev->discovery.scan_start = jiffies;
3975 hdev->discovery.scan_duration = timeout;
3976 }
3977
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003978 queue_delayed_work(hdev->workqueue,
3979 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003980 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003981
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003982unlock:
3983 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003984}
3985
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003986static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003987 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003988{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003989 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003990 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003991 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003992 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003993 int err;
3994
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003995 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003996
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003997 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003998
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003999 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004000 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4001 MGMT_STATUS_NOT_POWERED,
4002 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004003 goto failed;
4004 }
4005
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004006 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4007 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004008 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4009 MGMT_STATUS_BUSY, &cp->type,
4010 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004011 goto failed;
4012 }
4013
Johan Hedberg2922a942014-12-05 13:36:06 +02004014 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004015 if (!cmd) {
4016 err = -ENOMEM;
4017 goto failed;
4018 }
4019
Johan Hedberg2922a942014-12-05 13:36:06 +02004020 cmd->cmd_complete = generic_cmd_complete;
4021
Marcel Holtmann22078802014-12-05 11:45:22 +01004022 /* Clear the discovery filter first to free any previously
4023 * allocated memory for the UUID list.
4024 */
4025 hci_discovery_filter_clear(hdev);
4026
Andre Guedes4aab14e2012-02-17 20:39:36 -03004027 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004028 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004029
Andre Guedes7c307722013-04-30 15:29:28 -03004030 hci_req_init(&req, hdev);
4031
Marcel Holtmann80190442014-12-04 11:36:36 +01004032 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004033 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4034 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004035 mgmt_pending_remove(cmd);
4036 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004037 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004038
Andre Guedes7c307722013-04-30 15:29:28 -03004039 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004040 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004041 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004042 goto failed;
4043 }
4044
4045 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004046
4047failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004048 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004049 return err;
4050}
4051
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004052static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4053 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004054{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004055 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4056 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004057}
4058
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004059static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4060 void *data, u16 len)
4061{
4062 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004063 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004064 struct hci_request req;
4065 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4066 u16 uuid_count, expected_len;
4067 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004068 int err;
4069
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004070 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004071
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004072 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004073
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004074 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004075 err = mgmt_cmd_complete(sk, hdev->id,
4076 MGMT_OP_START_SERVICE_DISCOVERY,
4077 MGMT_STATUS_NOT_POWERED,
4078 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004079 goto failed;
4080 }
4081
4082 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4083 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004084 err = mgmt_cmd_complete(sk, hdev->id,
4085 MGMT_OP_START_SERVICE_DISCOVERY,
4086 MGMT_STATUS_BUSY, &cp->type,
4087 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004088 goto failed;
4089 }
4090
4091 uuid_count = __le16_to_cpu(cp->uuid_count);
4092 if (uuid_count > max_uuid_count) {
4093 BT_ERR("service_discovery: too big uuid_count value %u",
4094 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004095 err = mgmt_cmd_complete(sk, hdev->id,
4096 MGMT_OP_START_SERVICE_DISCOVERY,
4097 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4098 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004099 goto failed;
4100 }
4101
4102 expected_len = sizeof(*cp) + uuid_count * 16;
4103 if (expected_len != len) {
4104 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4105 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004106 err = mgmt_cmd_complete(sk, hdev->id,
4107 MGMT_OP_START_SERVICE_DISCOVERY,
4108 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4109 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004110 goto failed;
4111 }
4112
4113 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004114 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004115 if (!cmd) {
4116 err = -ENOMEM;
4117 goto failed;
4118 }
4119
Johan Hedberg2922a942014-12-05 13:36:06 +02004120 cmd->cmd_complete = service_discovery_cmd_complete;
4121
Marcel Holtmann22078802014-12-05 11:45:22 +01004122 /* Clear the discovery filter first to free any previously
4123 * allocated memory for the UUID list.
4124 */
4125 hci_discovery_filter_clear(hdev);
4126
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004127 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004128 hdev->discovery.type = cp->type;
4129 hdev->discovery.rssi = cp->rssi;
4130 hdev->discovery.uuid_count = uuid_count;
4131
4132 if (uuid_count > 0) {
4133 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4134 GFP_KERNEL);
4135 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004136 err = mgmt_cmd_complete(sk, hdev->id,
4137 MGMT_OP_START_SERVICE_DISCOVERY,
4138 MGMT_STATUS_FAILED,
4139 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004140 mgmt_pending_remove(cmd);
4141 goto failed;
4142 }
4143 }
4144
4145 hci_req_init(&req, hdev);
4146
4147 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004148 err = mgmt_cmd_complete(sk, hdev->id,
4149 MGMT_OP_START_SERVICE_DISCOVERY,
4150 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004151 mgmt_pending_remove(cmd);
4152 goto failed;
4153 }
4154
4155 err = hci_req_run(&req, start_discovery_complete);
4156 if (err < 0) {
4157 mgmt_pending_remove(cmd);
4158 goto failed;
4159 }
4160
4161 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4162
4163failed:
4164 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004165 return err;
4166}
4167
Marcel Holtmann1904a852015-01-11 13:50:44 -08004168static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004169{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004170 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004171
Andre Guedes0e05bba2013-04-30 15:29:33 -03004172 BT_DBG("status %d", status);
4173
4174 hci_dev_lock(hdev);
4175
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004176 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4177 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004178 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004179 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004180 }
4181
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004182 if (!status)
4183 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004184
Andre Guedes0e05bba2013-04-30 15:29:33 -03004185 hci_dev_unlock(hdev);
4186}
4187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004188static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004189 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004190{
Johan Hedbergd9306502012-02-20 23:25:18 +02004191 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004192 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004193 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004194 int err;
4195
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004196 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004197
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004198 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004199
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004200 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004201 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4202 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4203 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004204 goto unlock;
4205 }
4206
4207 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004208 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4209 MGMT_STATUS_INVALID_PARAMS,
4210 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004211 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004212 }
4213
Johan Hedberg2922a942014-12-05 13:36:06 +02004214 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004215 if (!cmd) {
4216 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004217 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004218 }
4219
Johan Hedberg2922a942014-12-05 13:36:06 +02004220 cmd->cmd_complete = generic_cmd_complete;
4221
Andre Guedes0e05bba2013-04-30 15:29:33 -03004222 hci_req_init(&req, hdev);
4223
Johan Hedberg21a60d32014-06-10 14:05:58 +03004224 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004225
Johan Hedberg21a60d32014-06-10 14:05:58 +03004226 err = hci_req_run(&req, stop_discovery_complete);
4227 if (!err) {
4228 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004229 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004230 }
4231
Johan Hedberg21a60d32014-06-10 14:05:58 +03004232 mgmt_pending_remove(cmd);
4233
4234 /* If no HCI commands were sent we're done */
4235 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004236 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4237 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004238 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4239 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004240
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004241unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004242 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004243 return err;
4244}
4245
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004246static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004247 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004248{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004249 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004250 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004251 int err;
4252
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004253 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004254
Johan Hedberg561aafb2012-01-04 13:31:59 +02004255 hci_dev_lock(hdev);
4256
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004257 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004258 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4259 MGMT_STATUS_FAILED, &cp->addr,
4260 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004261 goto failed;
4262 }
4263
Johan Hedberga198e7b2012-02-17 14:27:06 +02004264 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004265 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004266 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4267 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4268 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004269 goto failed;
4270 }
4271
4272 if (cp->name_known) {
4273 e->name_state = NAME_KNOWN;
4274 list_del(&e->list);
4275 } else {
4276 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004277 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004278 }
4279
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004280 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4281 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004282
4283failed:
4284 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004285 return err;
4286}
4287
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004288static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004289 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004290{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004291 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004292 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004293 int err;
4294
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004295 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004296
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004297 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004298 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4299 MGMT_STATUS_INVALID_PARAMS,
4300 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004301
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004302 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004303
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004304 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4305 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004306 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004307 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004308 goto done;
4309 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004310
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004311 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4312 sk);
4313 status = MGMT_STATUS_SUCCESS;
4314
4315done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004316 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4317 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004318
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004319 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004320
4321 return err;
4322}
4323
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004324static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004325 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004326{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004327 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004328 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004329 int err;
4330
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004331 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004332
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004333 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004334 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4335 MGMT_STATUS_INVALID_PARAMS,
4336 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004337
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004338 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004339
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004340 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4341 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004342 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004343 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004344 goto done;
4345 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004346
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004347 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4348 sk);
4349 status = MGMT_STATUS_SUCCESS;
4350
4351done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004352 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4353 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004354
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004355 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004356
4357 return err;
4358}
4359
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004360static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4361 u16 len)
4362{
4363 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004364 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004365 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004366 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004367
4368 BT_DBG("%s", hdev->name);
4369
Szymon Jancc72d4b82012-03-16 16:02:57 +01004370 source = __le16_to_cpu(cp->source);
4371
4372 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004373 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4374 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004375
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004376 hci_dev_lock(hdev);
4377
Szymon Jancc72d4b82012-03-16 16:02:57 +01004378 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004379 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4380 hdev->devid_product = __le16_to_cpu(cp->product);
4381 hdev->devid_version = __le16_to_cpu(cp->version);
4382
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004383 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4384 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004385
Johan Hedberg890ea892013-03-15 17:06:52 -05004386 hci_req_init(&req, hdev);
4387 update_eir(&req);
4388 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004389
4390 hci_dev_unlock(hdev);
4391
4392 return err;
4393}
4394
Marcel Holtmann1904a852015-01-11 13:50:44 -08004395static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4396 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004397{
4398 struct cmd_lookup match = { NULL, hdev };
4399
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304400 hci_dev_lock(hdev);
4401
Johan Hedberg4375f102013-09-25 13:26:10 +03004402 if (status) {
4403 u8 mgmt_err = mgmt_status(status);
4404
4405 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4406 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304407 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004408 }
4409
Johan Hedbergc93bd152014-07-08 15:07:48 +03004410 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4411 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4412 else
4413 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4414
Johan Hedberg4375f102013-09-25 13:26:10 +03004415 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4416 &match);
4417
4418 new_settings(hdev, match.sk);
4419
4420 if (match.sk)
4421 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304422
4423unlock:
4424 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004425}
4426
Marcel Holtmann21b51872013-10-10 09:47:53 -07004427static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4428 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004429{
4430 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004431 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004432 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004433 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004434 int err;
4435
4436 BT_DBG("request for %s", hdev->name);
4437
Johan Hedberge6fe7982013-10-02 15:45:22 +03004438 status = mgmt_le_support(hdev);
4439 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004440 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4441 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004442
4443 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004444 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4445 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004446
4447 hci_dev_lock(hdev);
4448
4449 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004450 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004451
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004452 /* The following conditions are ones which mean that we should
4453 * not do any HCI communication but directly send a mgmt
4454 * response to user space (after toggling the flag if
4455 * necessary).
4456 */
4457 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004458 hci_conn_num(hdev, LE_LINK) > 0 ||
4459 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4460 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004461 bool changed = false;
4462
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004463 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4464 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004465 changed = true;
4466 }
4467
4468 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4469 if (err < 0)
4470 goto unlock;
4471
4472 if (changed)
4473 err = new_settings(hdev, sk);
4474
4475 goto unlock;
4476 }
4477
4478 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4479 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004480 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4481 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004482 goto unlock;
4483 }
4484
4485 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4486 if (!cmd) {
4487 err = -ENOMEM;
4488 goto unlock;
4489 }
4490
4491 hci_req_init(&req, hdev);
4492
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004493 if (val)
4494 enable_advertising(&req);
4495 else
4496 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004497
4498 err = hci_req_run(&req, set_advertising_complete);
4499 if (err < 0)
4500 mgmt_pending_remove(cmd);
4501
4502unlock:
4503 hci_dev_unlock(hdev);
4504 return err;
4505}
4506
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004507static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4508 void *data, u16 len)
4509{
4510 struct mgmt_cp_set_static_address *cp = data;
4511 int err;
4512
4513 BT_DBG("%s", hdev->name);
4514
Marcel Holtmann62af4442013-10-02 22:10:32 -07004515 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004516 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4517 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004518
4519 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004520 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4521 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004522
4523 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4524 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004525 return mgmt_cmd_status(sk, hdev->id,
4526 MGMT_OP_SET_STATIC_ADDRESS,
4527 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004528
4529 /* Two most significant bits shall be set */
4530 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004531 return mgmt_cmd_status(sk, hdev->id,
4532 MGMT_OP_SET_STATIC_ADDRESS,
4533 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004534 }
4535
4536 hci_dev_lock(hdev);
4537
4538 bacpy(&hdev->static_addr, &cp->bdaddr);
4539
Marcel Holtmann93690c22015-03-06 10:11:21 -08004540 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4541 if (err < 0)
4542 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004543
Marcel Holtmann93690c22015-03-06 10:11:21 -08004544 err = new_settings(hdev, sk);
4545
4546unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004547 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004548 return err;
4549}
4550
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004551static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4552 void *data, u16 len)
4553{
4554 struct mgmt_cp_set_scan_params *cp = data;
4555 __u16 interval, window;
4556 int err;
4557
4558 BT_DBG("%s", hdev->name);
4559
4560 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004561 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4562 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004563
4564 interval = __le16_to_cpu(cp->interval);
4565
4566 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004567 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4568 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004569
4570 window = __le16_to_cpu(cp->window);
4571
4572 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004573 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4574 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004575
Marcel Holtmann899e1072013-10-14 09:55:32 -07004576 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004577 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4578 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004579
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004580 hci_dev_lock(hdev);
4581
4582 hdev->le_scan_interval = interval;
4583 hdev->le_scan_window = window;
4584
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004585 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4586 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004587
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004588 /* If background scan is running, restart it so new parameters are
4589 * loaded.
4590 */
4591 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4592 hdev->discovery.state == DISCOVERY_STOPPED) {
4593 struct hci_request req;
4594
4595 hci_req_init(&req, hdev);
4596
4597 hci_req_add_le_scan_disable(&req);
4598 hci_req_add_le_passive_scan(&req);
4599
4600 hci_req_run(&req, NULL);
4601 }
4602
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004603 hci_dev_unlock(hdev);
4604
4605 return err;
4606}
4607
Marcel Holtmann1904a852015-01-11 13:50:44 -08004608static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4609 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004610{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004611 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004612
4613 BT_DBG("status 0x%02x", status);
4614
4615 hci_dev_lock(hdev);
4616
4617 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4618 if (!cmd)
4619 goto unlock;
4620
4621 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004622 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4623 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004624 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004625 struct mgmt_mode *cp = cmd->param;
4626
4627 if (cp->val)
4628 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4629 else
4630 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4631
Johan Hedberg33e38b32013-03-15 17:07:05 -05004632 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4633 new_settings(hdev, cmd->sk);
4634 }
4635
4636 mgmt_pending_remove(cmd);
4637
4638unlock:
4639 hci_dev_unlock(hdev);
4640}
4641
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004642static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004643 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004644{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004645 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004646 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004647 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004648 int err;
4649
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004650 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004651
Johan Hedberg56f87902013-10-02 13:43:13 +03004652 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4653 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004654 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4655 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004656
Johan Hedberga7e80f22013-01-09 16:05:19 +02004657 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004658 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4659 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004660
Antti Julkuf6422ec2011-06-22 13:11:56 +03004661 hci_dev_lock(hdev);
4662
Johan Hedberg05cbf292013-03-15 17:07:07 -05004663 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004664 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4665 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004666 goto unlock;
4667 }
4668
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004669 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4670 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4671 hdev);
4672 goto unlock;
4673 }
4674
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004675 if (!hdev_is_powered(hdev)) {
4676 change_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4677 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4678 hdev);
4679 new_settings(hdev, sk);
4680 goto unlock;
4681 }
4682
Johan Hedberg33e38b32013-03-15 17:07:05 -05004683 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4684 data, len);
4685 if (!cmd) {
4686 err = -ENOMEM;
4687 goto unlock;
4688 }
4689
4690 hci_req_init(&req, hdev);
4691
Johan Hedberg406d7802013-03-15 17:07:09 -05004692 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004693
4694 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004695 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004696 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4697 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004698 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004699 }
4700
Johan Hedberg33e38b32013-03-15 17:07:05 -05004701unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004702 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004703
Antti Julkuf6422ec2011-06-22 13:11:56 +03004704 return err;
4705}
4706
Marcel Holtmann1904a852015-01-11 13:50:44 -08004707static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004708{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004709 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004710
4711 BT_DBG("status 0x%02x", status);
4712
4713 hci_dev_lock(hdev);
4714
4715 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4716 if (!cmd)
4717 goto unlock;
4718
4719 if (status) {
4720 u8 mgmt_err = mgmt_status(status);
4721
4722 /* We need to restore the flag if related HCI commands
4723 * failed.
4724 */
4725 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4726
Johan Hedberga69e8372015-03-06 21:08:53 +02004727 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004728 } else {
4729 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4730 new_settings(hdev, cmd->sk);
4731 }
4732
4733 mgmt_pending_remove(cmd);
4734
4735unlock:
4736 hci_dev_unlock(hdev);
4737}
4738
4739static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4740{
4741 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004742 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004743 struct hci_request req;
4744 int err;
4745
4746 BT_DBG("request for %s", hdev->name);
4747
4748 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004749 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4750 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004751
4752 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004753 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4754 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004755
4756 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004757 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4758 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004759
4760 hci_dev_lock(hdev);
4761
4762 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4763 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4764 goto unlock;
4765 }
4766
4767 if (!hdev_is_powered(hdev)) {
4768 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004769 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4770 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4771 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4772 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4773 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4774 }
4775
4776 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4777
4778 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4779 if (err < 0)
4780 goto unlock;
4781
4782 err = new_settings(hdev, sk);
4783 goto unlock;
4784 }
4785
4786 /* Reject disabling when powered on */
4787 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004788 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4789 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004790 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004791 } else {
4792 /* When configuring a dual-mode controller to operate
4793 * with LE only and using a static address, then switching
4794 * BR/EDR back on is not allowed.
4795 *
4796 * Dual-mode controllers shall operate with the public
4797 * address as its identity address for BR/EDR and LE. So
4798 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004799 *
4800 * The same restrictions applies when secure connections
4801 * has been enabled. For BR/EDR this is a controller feature
4802 * while for LE it is a host stack feature. This means that
4803 * switching BR/EDR back on when secure connections has been
4804 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004805 */
4806 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004807 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4808 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004809 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4810 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004811 goto unlock;
4812 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004813 }
4814
4815 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004816 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4817 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004818 goto unlock;
4819 }
4820
4821 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4822 if (!cmd) {
4823 err = -ENOMEM;
4824 goto unlock;
4825 }
4826
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004827 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004828 * generates the correct flags.
4829 */
4830 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4831
4832 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004833
Johan Hedberg432df052014-08-01 11:13:31 +03004834 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004835 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004836
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004837 /* Since only the advertising data flags will change, there
4838 * is no need to update the scan response data.
4839 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004840 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004841
Johan Hedberg0663ca22013-10-02 13:43:14 +03004842 err = hci_req_run(&req, set_bredr_complete);
4843 if (err < 0)
4844 mgmt_pending_remove(cmd);
4845
4846unlock:
4847 hci_dev_unlock(hdev);
4848 return err;
4849}
4850
Johan Hedberga1443f52015-01-23 15:42:46 +02004851static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4852{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004853 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004854 struct mgmt_mode *cp;
4855
4856 BT_DBG("%s status %u", hdev->name, status);
4857
4858 hci_dev_lock(hdev);
4859
4860 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4861 if (!cmd)
4862 goto unlock;
4863
4864 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004865 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4866 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004867 goto remove;
4868 }
4869
4870 cp = cmd->param;
4871
4872 switch (cp->val) {
4873 case 0x00:
4874 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4875 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4876 break;
4877 case 0x01:
4878 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4879 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4880 break;
4881 case 0x02:
4882 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4883 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4884 break;
4885 }
4886
4887 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4888 new_settings(hdev, cmd->sk);
4889
4890remove:
4891 mgmt_pending_remove(cmd);
4892unlock:
4893 hci_dev_unlock(hdev);
4894}
4895
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004896static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4897 void *data, u16 len)
4898{
4899 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004900 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004901 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004902 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004903 int err;
4904
4905 BT_DBG("request for %s", hdev->name);
4906
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004907 if (!lmp_sc_capable(hdev) &&
4908 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004909 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4910 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004911
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004912 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004913 lmp_sc_capable(hdev) &&
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004914 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004915 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4916 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004917
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004918 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004919 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004920 MGMT_STATUS_INVALID_PARAMS);
4921
4922 hci_dev_lock(hdev);
4923
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004924 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004925 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004926 bool changed;
4927
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004928 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004929 changed = !test_and_set_bit(HCI_SC_ENABLED,
4930 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004931 if (cp->val == 0x02)
4932 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4933 else
4934 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4935 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004936 changed = test_and_clear_bit(HCI_SC_ENABLED,
4937 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004938 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4939 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004940
4941 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4942 if (err < 0)
4943 goto failed;
4944
4945 if (changed)
4946 err = new_settings(hdev, sk);
4947
4948 goto failed;
4949 }
4950
4951 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004952 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4953 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004954 goto failed;
4955 }
4956
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004957 val = !!cp->val;
4958
4959 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4960 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004961 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4962 goto failed;
4963 }
4964
4965 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4966 if (!cmd) {
4967 err = -ENOMEM;
4968 goto failed;
4969 }
4970
Johan Hedberga1443f52015-01-23 15:42:46 +02004971 hci_req_init(&req, hdev);
4972 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4973 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004974 if (err < 0) {
4975 mgmt_pending_remove(cmd);
4976 goto failed;
4977 }
4978
4979failed:
4980 hci_dev_unlock(hdev);
4981 return err;
4982}
4983
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004984static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4985 void *data, u16 len)
4986{
4987 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004988 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004989 int err;
4990
4991 BT_DBG("request for %s", hdev->name);
4992
Johan Hedbergb97109792014-06-24 14:00:28 +03004993 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004994 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4995 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004996
4997 hci_dev_lock(hdev);
4998
4999 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03005000 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
5001 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005002 else
Johan Hedberg0663b292014-06-24 13:15:50 +03005003 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
5004 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005005
Johan Hedbergb97109792014-06-24 14:00:28 +03005006 if (cp->val == 0x02)
5007 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
5008 &hdev->dev_flags);
5009 else
5010 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
5011 &hdev->dev_flags);
5012
5013 if (hdev_is_powered(hdev) && use_changed &&
5014 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
5015 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5016 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5017 sizeof(mode), &mode);
5018 }
5019
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005020 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5021 if (err < 0)
5022 goto unlock;
5023
5024 if (changed)
5025 err = new_settings(hdev, sk);
5026
5027unlock:
5028 hci_dev_unlock(hdev);
5029 return err;
5030}
5031
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005032static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5033 u16 len)
5034{
5035 struct mgmt_cp_set_privacy *cp = cp_data;
5036 bool changed;
5037 int err;
5038
5039 BT_DBG("request for %s", hdev->name);
5040
5041 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005042 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5043 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005044
5045 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005046 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5047 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005048
5049 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005050 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5051 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005052
5053 hci_dev_lock(hdev);
5054
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005055 /* If user space supports this command it is also expected to
5056 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5057 */
5058 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5059
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005060 if (cp->privacy) {
5061 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5062 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5063 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5064 } else {
5065 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5066 memset(hdev->irk, 0, sizeof(hdev->irk));
5067 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5068 }
5069
5070 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5071 if (err < 0)
5072 goto unlock;
5073
5074 if (changed)
5075 err = new_settings(hdev, sk);
5076
5077unlock:
5078 hci_dev_unlock(hdev);
5079 return err;
5080}
5081
Johan Hedberg41edf162014-02-18 10:19:35 +02005082static bool irk_is_valid(struct mgmt_irk_info *irk)
5083{
5084 switch (irk->addr.type) {
5085 case BDADDR_LE_PUBLIC:
5086 return true;
5087
5088 case BDADDR_LE_RANDOM:
5089 /* Two most significant bits shall be set */
5090 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5091 return false;
5092 return true;
5093 }
5094
5095 return false;
5096}
5097
5098static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5099 u16 len)
5100{
5101 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005102 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5103 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005104 u16 irk_count, expected_len;
5105 int i, err;
5106
5107 BT_DBG("request for %s", hdev->name);
5108
5109 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005110 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5111 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005112
5113 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005114 if (irk_count > max_irk_count) {
5115 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005116 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5117 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005118 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005119
5120 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5121 if (expected_len != len) {
5122 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005123 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005124 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5125 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005126 }
5127
5128 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5129
5130 for (i = 0; i < irk_count; i++) {
5131 struct mgmt_irk_info *key = &cp->irks[i];
5132
5133 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005134 return mgmt_cmd_status(sk, hdev->id,
5135 MGMT_OP_LOAD_IRKS,
5136 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005137 }
5138
5139 hci_dev_lock(hdev);
5140
5141 hci_smp_irks_clear(hdev);
5142
5143 for (i = 0; i < irk_count; i++) {
5144 struct mgmt_irk_info *irk = &cp->irks[i];
5145 u8 addr_type;
5146
5147 if (irk->addr.type == BDADDR_LE_PUBLIC)
5148 addr_type = ADDR_LE_DEV_PUBLIC;
5149 else
5150 addr_type = ADDR_LE_DEV_RANDOM;
5151
5152 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5153 BDADDR_ANY);
5154 }
5155
5156 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5157
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005158 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005159
5160 hci_dev_unlock(hdev);
5161
5162 return err;
5163}
5164
Johan Hedberg3f706b72013-01-20 14:27:16 +02005165static bool ltk_is_valid(struct mgmt_ltk_info *key)
5166{
5167 if (key->master != 0x00 && key->master != 0x01)
5168 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005169
5170 switch (key->addr.type) {
5171 case BDADDR_LE_PUBLIC:
5172 return true;
5173
5174 case BDADDR_LE_RANDOM:
5175 /* Two most significant bits shall be set */
5176 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5177 return false;
5178 return true;
5179 }
5180
5181 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005182}
5183
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005184static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005185 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005186{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005187 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005188 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5189 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005190 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005191 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005192
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005193 BT_DBG("request for %s", hdev->name);
5194
5195 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005196 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5197 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005198
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005199 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005200 if (key_count > max_key_count) {
5201 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005202 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5203 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005204 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005205
5206 expected_len = sizeof(*cp) + key_count *
5207 sizeof(struct mgmt_ltk_info);
5208 if (expected_len != len) {
5209 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005210 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005211 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5212 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005213 }
5214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005215 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005216
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005217 for (i = 0; i < key_count; i++) {
5218 struct mgmt_ltk_info *key = &cp->keys[i];
5219
Johan Hedberg3f706b72013-01-20 14:27:16 +02005220 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005221 return mgmt_cmd_status(sk, hdev->id,
5222 MGMT_OP_LOAD_LONG_TERM_KEYS,
5223 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005224 }
5225
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005226 hci_dev_lock(hdev);
5227
5228 hci_smp_ltks_clear(hdev);
5229
5230 for (i = 0; i < key_count; i++) {
5231 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005232 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005233
5234 if (key->addr.type == BDADDR_LE_PUBLIC)
5235 addr_type = ADDR_LE_DEV_PUBLIC;
5236 else
5237 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005238
Johan Hedberg61b43352014-05-29 19:36:53 +03005239 switch (key->type) {
5240 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005241 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005242 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005243 break;
5244 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005245 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005246 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005247 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005248 case MGMT_LTK_P256_UNAUTH:
5249 authenticated = 0x00;
5250 type = SMP_LTK_P256;
5251 break;
5252 case MGMT_LTK_P256_AUTH:
5253 authenticated = 0x01;
5254 type = SMP_LTK_P256;
5255 break;
5256 case MGMT_LTK_P256_DEBUG:
5257 authenticated = 0x00;
5258 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005259 default:
5260 continue;
5261 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005262
Johan Hedberg35d70272014-02-19 14:57:47 +02005263 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005264 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005265 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005266 }
5267
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005268 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005269 NULL, 0);
5270
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005271 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005272
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005273 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005274}
5275
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005276static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005277{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005278 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005279 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005280 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005281
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005282 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005283
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005284 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005285 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005286 rp.tx_power = conn->tx_power;
5287 rp.max_tx_power = conn->max_tx_power;
5288 } else {
5289 rp.rssi = HCI_RSSI_INVALID;
5290 rp.tx_power = HCI_TX_POWER_INVALID;
5291 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005292 }
5293
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005294 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5295 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005296
5297 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005298 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005299
5300 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005301}
5302
Marcel Holtmann1904a852015-01-11 13:50:44 -08005303static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5304 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005305{
5306 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005307 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005308 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005309 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005310 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005311
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005312 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005313
5314 hci_dev_lock(hdev);
5315
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005316 /* Commands sent in request are either Read RSSI or Read Transmit Power
5317 * Level so we check which one was last sent to retrieve connection
5318 * handle. Both commands have handle as first parameter so it's safe to
5319 * cast data on the same command struct.
5320 *
5321 * First command sent is always Read RSSI and we fail only if it fails.
5322 * In other case we simply override error to indicate success as we
5323 * already remembered if TX power value is actually valid.
5324 */
5325 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5326 if (!cp) {
5327 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005328 status = MGMT_STATUS_SUCCESS;
5329 } else {
5330 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005331 }
5332
5333 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005334 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005335 goto unlock;
5336 }
5337
5338 handle = __le16_to_cpu(cp->handle);
5339 conn = hci_conn_hash_lookup_handle(hdev, handle);
5340 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005341 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005342 goto unlock;
5343 }
5344
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005345 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5346 if (!cmd)
5347 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005348
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005349 cmd->cmd_complete(cmd, status);
5350 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005351
5352unlock:
5353 hci_dev_unlock(hdev);
5354}
5355
5356static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5357 u16 len)
5358{
5359 struct mgmt_cp_get_conn_info *cp = data;
5360 struct mgmt_rp_get_conn_info rp;
5361 struct hci_conn *conn;
5362 unsigned long conn_info_age;
5363 int err = 0;
5364
5365 BT_DBG("%s", hdev->name);
5366
5367 memset(&rp, 0, sizeof(rp));
5368 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5369 rp.addr.type = cp->addr.type;
5370
5371 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005372 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5373 MGMT_STATUS_INVALID_PARAMS,
5374 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005375
5376 hci_dev_lock(hdev);
5377
5378 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005379 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5380 MGMT_STATUS_NOT_POWERED, &rp,
5381 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005382 goto unlock;
5383 }
5384
5385 if (cp->addr.type == BDADDR_BREDR)
5386 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5387 &cp->addr.bdaddr);
5388 else
5389 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5390
5391 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005392 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5393 MGMT_STATUS_NOT_CONNECTED, &rp,
5394 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005395 goto unlock;
5396 }
5397
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005398 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005399 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5400 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005401 goto unlock;
5402 }
5403
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005404 /* To avoid client trying to guess when to poll again for information we
5405 * calculate conn info age as random value between min/max set in hdev.
5406 */
5407 conn_info_age = hdev->conn_info_min_age +
5408 prandom_u32_max(hdev->conn_info_max_age -
5409 hdev->conn_info_min_age);
5410
5411 /* Query controller to refresh cached values if they are too old or were
5412 * never read.
5413 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005414 if (time_after(jiffies, conn->conn_info_timestamp +
5415 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005416 !conn->conn_info_timestamp) {
5417 struct hci_request req;
5418 struct hci_cp_read_tx_power req_txp_cp;
5419 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005420 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005421
5422 hci_req_init(&req, hdev);
5423 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5424 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5425 &req_rssi_cp);
5426
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005427 /* For LE links TX power does not change thus we don't need to
5428 * query for it once value is known.
5429 */
5430 if (!bdaddr_type_is_le(cp->addr.type) ||
5431 conn->tx_power == HCI_TX_POWER_INVALID) {
5432 req_txp_cp.handle = cpu_to_le16(conn->handle);
5433 req_txp_cp.type = 0x00;
5434 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5435 sizeof(req_txp_cp), &req_txp_cp);
5436 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005437
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005438 /* Max TX power needs to be read only once per connection */
5439 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5440 req_txp_cp.handle = cpu_to_le16(conn->handle);
5441 req_txp_cp.type = 0x01;
5442 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5443 sizeof(req_txp_cp), &req_txp_cp);
5444 }
5445
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005446 err = hci_req_run(&req, conn_info_refresh_complete);
5447 if (err < 0)
5448 goto unlock;
5449
5450 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5451 data, len);
5452 if (!cmd) {
5453 err = -ENOMEM;
5454 goto unlock;
5455 }
5456
5457 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005458 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005459 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005460
5461 conn->conn_info_timestamp = jiffies;
5462 } else {
5463 /* Cache is valid, just reply with values cached in hci_conn */
5464 rp.rssi = conn->rssi;
5465 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005466 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005467
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005468 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5469 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005470 }
5471
5472unlock:
5473 hci_dev_unlock(hdev);
5474 return err;
5475}
5476
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005477static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005478{
5479 struct hci_conn *conn = cmd->user_data;
5480 struct mgmt_rp_get_clock_info rp;
5481 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005482 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005483
5484 memset(&rp, 0, sizeof(rp));
5485 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5486
5487 if (status)
5488 goto complete;
5489
5490 hdev = hci_dev_get(cmd->index);
5491 if (hdev) {
5492 rp.local_clock = cpu_to_le32(hdev->clock);
5493 hci_dev_put(hdev);
5494 }
5495
5496 if (conn) {
5497 rp.piconet_clock = cpu_to_le32(conn->clock);
5498 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5499 }
5500
5501complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005502 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5503 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005504
5505 if (conn) {
5506 hci_conn_drop(conn);
5507 hci_conn_put(conn);
5508 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005509
5510 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005511}
5512
Marcel Holtmann1904a852015-01-11 13:50:44 -08005513static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005514{
Johan Hedberg95868422014-06-28 17:54:07 +03005515 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005516 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005517 struct hci_conn *conn;
5518
5519 BT_DBG("%s status %u", hdev->name, status);
5520
5521 hci_dev_lock(hdev);
5522
5523 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5524 if (!hci_cp)
5525 goto unlock;
5526
5527 if (hci_cp->which) {
5528 u16 handle = __le16_to_cpu(hci_cp->handle);
5529 conn = hci_conn_hash_lookup_handle(hdev, handle);
5530 } else {
5531 conn = NULL;
5532 }
5533
5534 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5535 if (!cmd)
5536 goto unlock;
5537
Johan Hedberg69487372014-12-05 13:36:07 +02005538 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005539 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005540
5541unlock:
5542 hci_dev_unlock(hdev);
5543}
5544
5545static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5546 u16 len)
5547{
5548 struct mgmt_cp_get_clock_info *cp = data;
5549 struct mgmt_rp_get_clock_info rp;
5550 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005551 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005552 struct hci_request req;
5553 struct hci_conn *conn;
5554 int err;
5555
5556 BT_DBG("%s", hdev->name);
5557
5558 memset(&rp, 0, sizeof(rp));
5559 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5560 rp.addr.type = cp->addr.type;
5561
5562 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005563 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5564 MGMT_STATUS_INVALID_PARAMS,
5565 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005566
5567 hci_dev_lock(hdev);
5568
5569 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005570 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5571 MGMT_STATUS_NOT_POWERED, &rp,
5572 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005573 goto unlock;
5574 }
5575
5576 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5577 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5578 &cp->addr.bdaddr);
5579 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005580 err = mgmt_cmd_complete(sk, hdev->id,
5581 MGMT_OP_GET_CLOCK_INFO,
5582 MGMT_STATUS_NOT_CONNECTED,
5583 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005584 goto unlock;
5585 }
5586 } else {
5587 conn = NULL;
5588 }
5589
5590 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5591 if (!cmd) {
5592 err = -ENOMEM;
5593 goto unlock;
5594 }
5595
Johan Hedberg69487372014-12-05 13:36:07 +02005596 cmd->cmd_complete = clock_info_cmd_complete;
5597
Johan Hedberg95868422014-06-28 17:54:07 +03005598 hci_req_init(&req, hdev);
5599
5600 memset(&hci_cp, 0, sizeof(hci_cp));
5601 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5602
5603 if (conn) {
5604 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005605 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005606
5607 hci_cp.handle = cpu_to_le16(conn->handle);
5608 hci_cp.which = 0x01; /* Piconet clock */
5609 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5610 }
5611
5612 err = hci_req_run(&req, get_clock_info_complete);
5613 if (err < 0)
5614 mgmt_pending_remove(cmd);
5615
5616unlock:
5617 hci_dev_unlock(hdev);
5618 return err;
5619}
5620
Johan Hedberg5a154e62014-12-19 22:26:02 +02005621static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5622{
5623 struct hci_conn *conn;
5624
5625 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5626 if (!conn)
5627 return false;
5628
5629 if (conn->dst_type != type)
5630 return false;
5631
5632 if (conn->state != BT_CONNECTED)
5633 return false;
5634
5635 return true;
5636}
5637
5638/* This function requires the caller holds hdev->lock */
5639static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5640 u8 addr_type, u8 auto_connect)
5641{
5642 struct hci_dev *hdev = req->hdev;
5643 struct hci_conn_params *params;
5644
5645 params = hci_conn_params_add(hdev, addr, addr_type);
5646 if (!params)
5647 return -EIO;
5648
5649 if (params->auto_connect == auto_connect)
5650 return 0;
5651
5652 list_del_init(&params->action);
5653
5654 switch (auto_connect) {
5655 case HCI_AUTO_CONN_DISABLED:
5656 case HCI_AUTO_CONN_LINK_LOSS:
5657 __hci_update_background_scan(req);
5658 break;
5659 case HCI_AUTO_CONN_REPORT:
5660 list_add(&params->action, &hdev->pend_le_reports);
5661 __hci_update_background_scan(req);
5662 break;
5663 case HCI_AUTO_CONN_DIRECT:
5664 case HCI_AUTO_CONN_ALWAYS:
5665 if (!is_connected(hdev, addr, addr_type)) {
5666 list_add(&params->action, &hdev->pend_le_conns);
5667 __hci_update_background_scan(req);
5668 }
5669 break;
5670 }
5671
5672 params->auto_connect = auto_connect;
5673
5674 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5675 auto_connect);
5676
5677 return 0;
5678}
5679
Marcel Holtmann8afef092014-06-29 22:28:34 +02005680static void device_added(struct sock *sk, struct hci_dev *hdev,
5681 bdaddr_t *bdaddr, u8 type, u8 action)
5682{
5683 struct mgmt_ev_device_added ev;
5684
5685 bacpy(&ev.addr.bdaddr, bdaddr);
5686 ev.addr.type = type;
5687 ev.action = action;
5688
5689 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5690}
5691
Marcel Holtmann1904a852015-01-11 13:50:44 -08005692static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005693{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005694 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005695
5696 BT_DBG("status 0x%02x", status);
5697
5698 hci_dev_lock(hdev);
5699
5700 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5701 if (!cmd)
5702 goto unlock;
5703
5704 cmd->cmd_complete(cmd, mgmt_status(status));
5705 mgmt_pending_remove(cmd);
5706
5707unlock:
5708 hci_dev_unlock(hdev);
5709}
5710
Marcel Holtmann2faade52014-06-29 19:44:03 +02005711static int add_device(struct sock *sk, struct hci_dev *hdev,
5712 void *data, u16 len)
5713{
5714 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005715 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005716 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005717 u8 auto_conn, addr_type;
5718 int err;
5719
5720 BT_DBG("%s", hdev->name);
5721
Johan Hedberg66593582014-07-09 12:59:14 +03005722 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005723 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005724 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5725 MGMT_STATUS_INVALID_PARAMS,
5726 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005727
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005728 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005729 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5730 MGMT_STATUS_INVALID_PARAMS,
5731 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005732
Johan Hedberg5a154e62014-12-19 22:26:02 +02005733 hci_req_init(&req, hdev);
5734
Marcel Holtmann2faade52014-06-29 19:44:03 +02005735 hci_dev_lock(hdev);
5736
Johan Hedberg5a154e62014-12-19 22:26:02 +02005737 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5738 if (!cmd) {
5739 err = -ENOMEM;
5740 goto unlock;
5741 }
5742
5743 cmd->cmd_complete = addr_cmd_complete;
5744
Johan Hedberg66593582014-07-09 12:59:14 +03005745 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005746 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005747 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005748 err = cmd->cmd_complete(cmd,
5749 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005750 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005751 goto unlock;
5752 }
5753
5754 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5755 cp->addr.type);
5756 if (err)
5757 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005758
Johan Hedberg5a154e62014-12-19 22:26:02 +02005759 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005760
Johan Hedberg66593582014-07-09 12:59:14 +03005761 goto added;
5762 }
5763
Marcel Holtmann2faade52014-06-29 19:44:03 +02005764 if (cp->addr.type == BDADDR_LE_PUBLIC)
5765 addr_type = ADDR_LE_DEV_PUBLIC;
5766 else
5767 addr_type = ADDR_LE_DEV_RANDOM;
5768
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005769 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005770 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005771 else if (cp->action == 0x01)
5772 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005773 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005774 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005775
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005776 /* If the connection parameters don't exist for this device,
5777 * they will be created and configured with defaults.
5778 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005779 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005780 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005781 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005782 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005783 goto unlock;
5784 }
5785
Johan Hedberg66593582014-07-09 12:59:14 +03005786added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005787 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5788
Johan Hedberg5a154e62014-12-19 22:26:02 +02005789 err = hci_req_run(&req, add_device_complete);
5790 if (err < 0) {
5791 /* ENODATA means no HCI commands were needed (e.g. if
5792 * the adapter is powered off).
5793 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005794 if (err == -ENODATA)
5795 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005796 mgmt_pending_remove(cmd);
5797 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005798
5799unlock:
5800 hci_dev_unlock(hdev);
5801 return err;
5802}
5803
Marcel Holtmann8afef092014-06-29 22:28:34 +02005804static void device_removed(struct sock *sk, struct hci_dev *hdev,
5805 bdaddr_t *bdaddr, u8 type)
5806{
5807 struct mgmt_ev_device_removed ev;
5808
5809 bacpy(&ev.addr.bdaddr, bdaddr);
5810 ev.addr.type = type;
5811
5812 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5813}
5814
Marcel Holtmann1904a852015-01-11 13:50:44 -08005815static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005816{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005817 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005818
5819 BT_DBG("status 0x%02x", status);
5820
5821 hci_dev_lock(hdev);
5822
5823 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5824 if (!cmd)
5825 goto unlock;
5826
5827 cmd->cmd_complete(cmd, mgmt_status(status));
5828 mgmt_pending_remove(cmd);
5829
5830unlock:
5831 hci_dev_unlock(hdev);
5832}
5833
Marcel Holtmann2faade52014-06-29 19:44:03 +02005834static int remove_device(struct sock *sk, struct hci_dev *hdev,
5835 void *data, u16 len)
5836{
5837 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005838 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005839 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005840 int err;
5841
5842 BT_DBG("%s", hdev->name);
5843
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005844 hci_req_init(&req, hdev);
5845
Marcel Holtmann2faade52014-06-29 19:44:03 +02005846 hci_dev_lock(hdev);
5847
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005848 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5849 if (!cmd) {
5850 err = -ENOMEM;
5851 goto unlock;
5852 }
5853
5854 cmd->cmd_complete = addr_cmd_complete;
5855
Marcel Holtmann2faade52014-06-29 19:44:03 +02005856 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005857 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005858 u8 addr_type;
5859
Johan Hedberg66593582014-07-09 12:59:14 +03005860 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005861 err = cmd->cmd_complete(cmd,
5862 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005863 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005864 goto unlock;
5865 }
5866
Johan Hedberg66593582014-07-09 12:59:14 +03005867 if (cp->addr.type == BDADDR_BREDR) {
5868 err = hci_bdaddr_list_del(&hdev->whitelist,
5869 &cp->addr.bdaddr,
5870 cp->addr.type);
5871 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005872 err = cmd->cmd_complete(cmd,
5873 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005874 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005875 goto unlock;
5876 }
5877
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005878 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005879
Johan Hedberg66593582014-07-09 12:59:14 +03005880 device_removed(sk, hdev, &cp->addr.bdaddr,
5881 cp->addr.type);
5882 goto complete;
5883 }
5884
Marcel Holtmann2faade52014-06-29 19:44:03 +02005885 if (cp->addr.type == BDADDR_LE_PUBLIC)
5886 addr_type = ADDR_LE_DEV_PUBLIC;
5887 else
5888 addr_type = ADDR_LE_DEV_RANDOM;
5889
Johan Hedbergc71593d2014-07-02 17:37:28 +03005890 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5891 addr_type);
5892 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005893 err = cmd->cmd_complete(cmd,
5894 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005895 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005896 goto unlock;
5897 }
5898
5899 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005900 err = cmd->cmd_complete(cmd,
5901 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005902 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005903 goto unlock;
5904 }
5905
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005906 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005907 list_del(&params->list);
5908 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005909 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005910
5911 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005912 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005913 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005914 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005915
Marcel Holtmann2faade52014-06-29 19:44:03 +02005916 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005917 err = cmd->cmd_complete(cmd,
5918 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005919 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005920 goto unlock;
5921 }
5922
Johan Hedberg66593582014-07-09 12:59:14 +03005923 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5924 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5925 list_del(&b->list);
5926 kfree(b);
5927 }
5928
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005929 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005930
Johan Hedberg19de0822014-07-06 13:06:51 +03005931 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5932 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5933 continue;
5934 device_removed(sk, hdev, &p->addr, p->addr_type);
5935 list_del(&p->action);
5936 list_del(&p->list);
5937 kfree(p);
5938 }
5939
5940 BT_DBG("All LE connection parameters were removed");
5941
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005942 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005943 }
5944
Johan Hedberg66593582014-07-09 12:59:14 +03005945complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005946 err = hci_req_run(&req, remove_device_complete);
5947 if (err < 0) {
5948 /* ENODATA means no HCI commands were needed (e.g. if
5949 * the adapter is powered off).
5950 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005951 if (err == -ENODATA)
5952 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005953 mgmt_pending_remove(cmd);
5954 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005955
5956unlock:
5957 hci_dev_unlock(hdev);
5958 return err;
5959}
5960
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005961static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5962 u16 len)
5963{
5964 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005965 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5966 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005967 u16 param_count, expected_len;
5968 int i;
5969
5970 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005971 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5972 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005973
5974 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005975 if (param_count > max_param_count) {
5976 BT_ERR("load_conn_param: too big param_count value %u",
5977 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005978 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5979 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005980 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005981
5982 expected_len = sizeof(*cp) + param_count *
5983 sizeof(struct mgmt_conn_param);
5984 if (expected_len != len) {
5985 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5986 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005987 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5988 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005989 }
5990
5991 BT_DBG("%s param_count %u", hdev->name, param_count);
5992
5993 hci_dev_lock(hdev);
5994
5995 hci_conn_params_clear_disabled(hdev);
5996
5997 for (i = 0; i < param_count; i++) {
5998 struct mgmt_conn_param *param = &cp->params[i];
5999 struct hci_conn_params *hci_param;
6000 u16 min, max, latency, timeout;
6001 u8 addr_type;
6002
6003 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6004 param->addr.type);
6005
6006 if (param->addr.type == BDADDR_LE_PUBLIC) {
6007 addr_type = ADDR_LE_DEV_PUBLIC;
6008 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6009 addr_type = ADDR_LE_DEV_RANDOM;
6010 } else {
6011 BT_ERR("Ignoring invalid connection parameters");
6012 continue;
6013 }
6014
6015 min = le16_to_cpu(param->min_interval);
6016 max = le16_to_cpu(param->max_interval);
6017 latency = le16_to_cpu(param->latency);
6018 timeout = le16_to_cpu(param->timeout);
6019
6020 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6021 min, max, latency, timeout);
6022
6023 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6024 BT_ERR("Ignoring invalid connection parameters");
6025 continue;
6026 }
6027
6028 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6029 addr_type);
6030 if (!hci_param) {
6031 BT_ERR("Failed to add connection parameters");
6032 continue;
6033 }
6034
6035 hci_param->conn_min_interval = min;
6036 hci_param->conn_max_interval = max;
6037 hci_param->conn_latency = latency;
6038 hci_param->supervision_timeout = timeout;
6039 }
6040
6041 hci_dev_unlock(hdev);
6042
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006043 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6044 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006045}
6046
Marcel Holtmanndbece372014-07-04 18:11:55 +02006047static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6048 void *data, u16 len)
6049{
6050 struct mgmt_cp_set_external_config *cp = data;
6051 bool changed;
6052 int err;
6053
6054 BT_DBG("%s", hdev->name);
6055
6056 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006057 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6058 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006059
6060 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006061 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6062 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006063
6064 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006065 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6066 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006067
6068 hci_dev_lock(hdev);
6069
6070 if (cp->config)
6071 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6072 &hdev->dev_flags);
6073 else
6074 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6075 &hdev->dev_flags);
6076
6077 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6078 if (err < 0)
6079 goto unlock;
6080
6081 if (!changed)
6082 goto unlock;
6083
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006084 err = new_options(hdev, sk);
6085
Marcel Holtmanndbece372014-07-04 18:11:55 +02006086 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
6087 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006088
6089 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6090 set_bit(HCI_CONFIG, &hdev->dev_flags);
6091 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6092
6093 queue_work(hdev->req_workqueue, &hdev->power_on);
6094 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006095 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006096 mgmt_index_added(hdev);
6097 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006098 }
6099
6100unlock:
6101 hci_dev_unlock(hdev);
6102 return err;
6103}
6104
Marcel Holtmann9713c172014-07-06 12:11:15 +02006105static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6106 void *data, u16 len)
6107{
6108 struct mgmt_cp_set_public_address *cp = data;
6109 bool changed;
6110 int err;
6111
6112 BT_DBG("%s", hdev->name);
6113
6114 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006115 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6116 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006117
6118 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006119 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6120 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006121
6122 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006123 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6124 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006125
6126 hci_dev_lock(hdev);
6127
6128 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6129 bacpy(&hdev->public_addr, &cp->bdaddr);
6130
6131 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6132 if (err < 0)
6133 goto unlock;
6134
6135 if (!changed)
6136 goto unlock;
6137
6138 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6139 err = new_options(hdev, sk);
6140
6141 if (is_configured(hdev)) {
6142 mgmt_index_removed(hdev);
6143
6144 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6145
6146 set_bit(HCI_CONFIG, &hdev->dev_flags);
6147 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6148
6149 queue_work(hdev->req_workqueue, &hdev->power_on);
6150 }
6151
6152unlock:
6153 hci_dev_unlock(hdev);
6154 return err;
6155}
6156
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006157static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006158 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006159 { read_version, MGMT_READ_VERSION_SIZE,
6160 HCI_MGMT_NO_HDEV },
6161 { read_commands, MGMT_READ_COMMANDS_SIZE,
6162 HCI_MGMT_NO_HDEV },
6163 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6164 HCI_MGMT_NO_HDEV },
6165 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6166 { set_powered, MGMT_SETTING_SIZE, 0 },
6167 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6168 { set_connectable, MGMT_SETTING_SIZE, 0 },
6169 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6170 { set_bondable, MGMT_SETTING_SIZE, 0 },
6171 { set_link_security, MGMT_SETTING_SIZE, 0 },
6172 { set_ssp, MGMT_SETTING_SIZE, 0 },
6173 { set_hs, MGMT_SETTING_SIZE, 0 },
6174 { set_le, MGMT_SETTING_SIZE, 0 },
6175 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6176 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6177 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6178 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6179 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6180 HCI_MGMT_VAR_LEN },
6181 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6182 HCI_MGMT_VAR_LEN },
6183 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6184 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6185 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6186 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6187 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6188 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6189 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6190 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6191 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6192 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6193 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6194 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6195 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6196 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6197 HCI_MGMT_VAR_LEN },
6198 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6199 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6200 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6201 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6202 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6203 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6204 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6205 { set_advertising, MGMT_SETTING_SIZE, 0 },
6206 { set_bredr, MGMT_SETTING_SIZE, 0 },
6207 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6208 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6209 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6210 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6211 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6212 { load_irks, MGMT_LOAD_IRKS_SIZE,
6213 HCI_MGMT_VAR_LEN },
6214 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6215 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6216 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6217 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6218 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6219 HCI_MGMT_VAR_LEN },
6220 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6221 HCI_MGMT_NO_HDEV },
6222 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6223 HCI_MGMT_UNCONFIGURED },
6224 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6225 HCI_MGMT_UNCONFIGURED },
6226 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6227 HCI_MGMT_UNCONFIGURED },
6228 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6229 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006230};
6231
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006232int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6233 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006234{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006235 void *buf;
6236 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006237 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006238 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006239 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006240 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006241 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006242 int err;
6243
6244 BT_DBG("got %zu bytes", msglen);
6245
6246 if (msglen < sizeof(*hdr))
6247 return -EINVAL;
6248
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006249 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006250 if (!buf)
6251 return -ENOMEM;
6252
Al Viro6ce8e9c2014-04-06 21:25:44 -04006253 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006254 err = -EFAULT;
6255 goto done;
6256 }
6257
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006258 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006259 opcode = __le16_to_cpu(hdr->opcode);
6260 index = __le16_to_cpu(hdr->index);
6261 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006262
6263 if (len != msglen - sizeof(*hdr)) {
6264 err = -EINVAL;
6265 goto done;
6266 }
6267
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006268 if (opcode >= chan->handler_count ||
6269 chan->handlers[opcode].func == NULL) {
6270 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006271 err = mgmt_cmd_status(sk, index, opcode,
6272 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006273 goto done;
6274 }
6275
6276 handler = &chan->handlers[opcode];
6277
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006278 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006279 hdev = hci_dev_get(index);
6280 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006281 err = mgmt_cmd_status(sk, index, opcode,
6282 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006283 goto done;
6284 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006285
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006286 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02006287 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006288 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006289 err = mgmt_cmd_status(sk, index, opcode,
6290 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006291 goto done;
6292 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006293
6294 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006295 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006296 err = mgmt_cmd_status(sk, index, opcode,
6297 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006298 goto done;
6299 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006300 }
6301
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006302 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6303 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006304 err = mgmt_cmd_status(sk, index, opcode,
6305 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006306 goto done;
6307 }
6308
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006309 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6310 if ((var_len && len < handler->data_len) ||
6311 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006312 err = mgmt_cmd_status(sk, index, opcode,
6313 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006314 goto done;
6315 }
6316
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006317 if (hdev)
6318 mgmt_init_hdev(sk, hdev);
6319
6320 cp = buf + sizeof(*hdr);
6321
Johan Hedbergbe22b542012-03-01 22:24:41 +02006322 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006323 if (err < 0)
6324 goto done;
6325
Johan Hedberg03811012010-12-08 00:21:06 +02006326 err = msglen;
6327
6328done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006329 if (hdev)
6330 hci_dev_put(hdev);
6331
Johan Hedberg03811012010-12-08 00:21:06 +02006332 kfree(buf);
6333 return err;
6334}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006335
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006336void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006337{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006338 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006339 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006340
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006341 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6342 return;
6343
6344 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6345 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6346 else
6347 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006348}
6349
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006350void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006351{
Johan Hedberg5f159032012-03-02 03:13:19 +02006352 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006353
Marcel Holtmann1514b892013-10-06 08:25:01 -07006354 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006355 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006356
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006357 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6358 return;
6359
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006360 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006361
Marcel Holtmannedd38962014-07-02 21:30:55 +02006362 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6363 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6364 else
6365 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006366}
6367
Andre Guedes6046dc32014-02-26 20:21:51 -03006368/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006369static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006370{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006371 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006372 struct hci_conn_params *p;
6373
6374 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006375 /* Needed for AUTO_OFF case where might not "really"
6376 * have been powered off.
6377 */
6378 list_del_init(&p->action);
6379
6380 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006381 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006382 case HCI_AUTO_CONN_ALWAYS:
6383 list_add(&p->action, &hdev->pend_le_conns);
6384 break;
6385 case HCI_AUTO_CONN_REPORT:
6386 list_add(&p->action, &hdev->pend_le_reports);
6387 break;
6388 default:
6389 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006390 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006391 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006392
Johan Hedberg2cf22212014-12-19 22:26:00 +02006393 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006394}
6395
Marcel Holtmann1904a852015-01-11 13:50:44 -08006396static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006397{
6398 struct cmd_lookup match = { NULL, hdev };
6399
6400 BT_DBG("status 0x%02x", status);
6401
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006402 if (!status) {
6403 /* Register the available SMP channels (BR/EDR and LE) only
6404 * when successfully powering on the controller. This late
6405 * registration is required so that LE SMP can clearly
6406 * decide if the public address or static address is used.
6407 */
6408 smp_register(hdev);
6409 }
6410
Johan Hedberg229ab392013-03-15 17:06:53 -05006411 hci_dev_lock(hdev);
6412
6413 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6414
6415 new_settings(hdev, match.sk);
6416
6417 hci_dev_unlock(hdev);
6418
6419 if (match.sk)
6420 sock_put(match.sk);
6421}
6422
Johan Hedberg70da6242013-03-15 17:06:51 -05006423static int powered_update_hci(struct hci_dev *hdev)
6424{
Johan Hedberg890ea892013-03-15 17:06:52 -05006425 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006426 u8 link_sec;
6427
Johan Hedberg890ea892013-03-15 17:06:52 -05006428 hci_req_init(&req, hdev);
6429
Johan Hedberg70da6242013-03-15 17:06:51 -05006430 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6431 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006432 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006433
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006434 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006435
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006436 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6437 u8 support = 0x01;
6438
6439 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6440 sizeof(support), &support);
6441 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006442 }
6443
Johan Hedbergc73eee92013-04-19 18:35:21 +03006444 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6445 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006446 struct hci_cp_write_le_host_supported cp;
6447
Marcel Holtmann32226e42014-07-24 20:04:16 +02006448 cp.le = 0x01;
6449 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006450
6451 /* Check first if we already have the right
6452 * host state (host features set)
6453 */
6454 if (cp.le != lmp_host_le_capable(hdev) ||
6455 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006456 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6457 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006458 }
6459
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006460 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006461 /* Make sure the controller has a good default for
6462 * advertising data. This also applies to the case
6463 * where BR/EDR was toggled during the AUTO_OFF phase.
6464 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006465 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006466 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006467 update_scan_rsp_data(&req);
6468 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006469
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006470 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6471 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006472
6473 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006474 }
6475
Johan Hedberg70da6242013-03-15 17:06:51 -05006476 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6477 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006478 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6479 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006480
6481 if (lmp_bredr_capable(hdev)) {
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006482 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
6483 write_fast_connectable(&req, true);
6484 else
6485 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006486 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006487 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006488 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006489 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006490 }
6491
Johan Hedberg229ab392013-03-15 17:06:53 -05006492 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006493}
6494
Johan Hedberg744cf192011-11-08 20:40:14 +02006495int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006496{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006497 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006498 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006499 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006500
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006501 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6502 return 0;
6503
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006504 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006505 if (powered_update_hci(hdev) == 0)
6506 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006507
Johan Hedberg229ab392013-03-15 17:06:53 -05006508 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6509 &match);
6510 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006511 }
6512
Johan Hedberg229ab392013-03-15 17:06:53 -05006513 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006514
6515 /* If the power off is because of hdev unregistration let
6516 * use the appropriate INVALID_INDEX status. Otherwise use
6517 * NOT_POWERED. We cover both scenarios here since later in
6518 * mgmt_index_removed() any hci_conn callbacks will have already
6519 * been triggered, potentially causing misleading DISCONNECTED
6520 * status responses.
6521 */
6522 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6523 status = MGMT_STATUS_INVALID_INDEX;
6524 else
6525 status = MGMT_STATUS_NOT_POWERED;
6526
6527 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006528
6529 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6530 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6531 zero_cod, sizeof(zero_cod), NULL);
6532
6533new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006534 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006535
6536 if (match.sk)
6537 sock_put(match.sk);
6538
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006539 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006540}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006541
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006542void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006543{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006544 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006545 u8 status;
6546
6547 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6548 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006549 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006550
6551 if (err == -ERFKILL)
6552 status = MGMT_STATUS_RFKILLED;
6553 else
6554 status = MGMT_STATUS_FAILED;
6555
Johan Hedberga69e8372015-03-06 21:08:53 +02006556 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006557
6558 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006559}
6560
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006561void mgmt_discoverable_timeout(struct hci_dev *hdev)
6562{
6563 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006564
6565 hci_dev_lock(hdev);
6566
6567 /* When discoverable timeout triggers, then just make sure
6568 * the limited discoverable flag is cleared. Even in the case
6569 * of a timeout triggered from general discoverable, it is
6570 * safe to unconditionally clear the flag.
6571 */
6572 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006573 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006574
6575 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006576 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6577 u8 scan = SCAN_PAGE;
6578 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6579 sizeof(scan), &scan);
6580 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006581 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006582 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006583 hci_req_run(&req, NULL);
6584
6585 hdev->discov_timeout = 0;
6586
Johan Hedberg9a43e252013-10-20 19:00:07 +03006587 new_settings(hdev, NULL);
6588
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006589 hci_dev_unlock(hdev);
6590}
6591
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006592void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6593 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006594{
Johan Hedberg86742e12011-11-07 23:13:38 +02006595 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006596
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006597 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006598
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006599 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006600 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006601 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006602 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006603 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006604 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006605
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006606 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006607}
Johan Hedbergf7520542011-01-20 12:34:39 +02006608
Johan Hedbergd7b25452014-05-23 13:19:53 +03006609static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6610{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006611 switch (ltk->type) {
6612 case SMP_LTK:
6613 case SMP_LTK_SLAVE:
6614 if (ltk->authenticated)
6615 return MGMT_LTK_AUTHENTICATED;
6616 return MGMT_LTK_UNAUTHENTICATED;
6617 case SMP_LTK_P256:
6618 if (ltk->authenticated)
6619 return MGMT_LTK_P256_AUTH;
6620 return MGMT_LTK_P256_UNAUTH;
6621 case SMP_LTK_P256_DEBUG:
6622 return MGMT_LTK_P256_DEBUG;
6623 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006624
6625 return MGMT_LTK_UNAUTHENTICATED;
6626}
6627
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006628void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006629{
6630 struct mgmt_ev_new_long_term_key ev;
6631
6632 memset(&ev, 0, sizeof(ev));
6633
Marcel Holtmann5192d302014-02-19 17:11:58 -08006634 /* Devices using resolvable or non-resolvable random addresses
6635 * without providing an indentity resolving key don't require
6636 * to store long term keys. Their addresses will change the
6637 * next time around.
6638 *
6639 * Only when a remote device provides an identity address
6640 * make sure the long term key is stored. If the remote
6641 * identity is known, the long term keys are internally
6642 * mapped to the identity address. So allow static random
6643 * and public addresses here.
6644 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006645 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6646 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6647 ev.store_hint = 0x00;
6648 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006649 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006650
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006651 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006652 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006653 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006654 ev.key.enc_size = key->enc_size;
6655 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006656 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006657
Johan Hedberg2ceba532014-06-16 19:25:16 +03006658 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006659 ev.key.master = 1;
6660
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006661 memcpy(ev.key.val, key->val, sizeof(key->val));
6662
Marcel Holtmann083368f2013-10-15 14:26:29 -07006663 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006664}
6665
Johan Hedberg95fbac82014-02-19 15:18:31 +02006666void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6667{
6668 struct mgmt_ev_new_irk ev;
6669
6670 memset(&ev, 0, sizeof(ev));
6671
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006672 /* For identity resolving keys from devices that are already
6673 * using a public address or static random address, do not
6674 * ask for storing this key. The identity resolving key really
6675 * is only mandatory for devices using resovlable random
6676 * addresses.
6677 *
6678 * Storing all identity resolving keys has the downside that
6679 * they will be also loaded on next boot of they system. More
6680 * identity resolving keys, means more time during scanning is
6681 * needed to actually resolve these addresses.
6682 */
6683 if (bacmp(&irk->rpa, BDADDR_ANY))
6684 ev.store_hint = 0x01;
6685 else
6686 ev.store_hint = 0x00;
6687
Johan Hedberg95fbac82014-02-19 15:18:31 +02006688 bacpy(&ev.rpa, &irk->rpa);
6689 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6690 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6691 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6692
6693 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6694}
6695
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006696void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6697 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006698{
6699 struct mgmt_ev_new_csrk ev;
6700
6701 memset(&ev, 0, sizeof(ev));
6702
6703 /* Devices using resolvable or non-resolvable random addresses
6704 * without providing an indentity resolving key don't require
6705 * to store signature resolving keys. Their addresses will change
6706 * the next time around.
6707 *
6708 * Only when a remote device provides an identity address
6709 * make sure the signature resolving key is stored. So allow
6710 * static random and public addresses here.
6711 */
6712 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6713 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6714 ev.store_hint = 0x00;
6715 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006716 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006717
6718 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6719 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006720 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006721 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6722
6723 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6724}
6725
Andre Guedesffb5a8272014-07-01 18:10:11 -03006726void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006727 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6728 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006729{
6730 struct mgmt_ev_new_conn_param ev;
6731
Johan Hedbergc103aea2014-07-02 17:37:34 +03006732 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6733 return;
6734
Andre Guedesffb5a8272014-07-01 18:10:11 -03006735 memset(&ev, 0, sizeof(ev));
6736 bacpy(&ev.addr.bdaddr, bdaddr);
6737 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006738 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006739 ev.min_interval = cpu_to_le16(min_interval);
6740 ev.max_interval = cpu_to_le16(max_interval);
6741 ev.latency = cpu_to_le16(latency);
6742 ev.timeout = cpu_to_le16(timeout);
6743
6744 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6745}
6746
Marcel Holtmann94933992013-10-15 10:26:39 -07006747static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6748 u8 data_len)
6749{
6750 eir[eir_len++] = sizeof(type) + data_len;
6751 eir[eir_len++] = type;
6752 memcpy(&eir[eir_len], data, data_len);
6753 eir_len += data_len;
6754
6755 return eir_len;
6756}
6757
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006758void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6759 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006760{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006761 char buf[512];
6762 struct mgmt_ev_device_connected *ev = (void *) buf;
6763 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006764
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006765 bacpy(&ev->addr.bdaddr, &conn->dst);
6766 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006767
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006768 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006769
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006770 /* We must ensure that the EIR Data fields are ordered and
6771 * unique. Keep it simple for now and avoid the problem by not
6772 * adding any BR/EDR data to the LE adv.
6773 */
6774 if (conn->le_adv_data_len > 0) {
6775 memcpy(&ev->eir[eir_len],
6776 conn->le_adv_data, conn->le_adv_data_len);
6777 eir_len = conn->le_adv_data_len;
6778 } else {
6779 if (name_len > 0)
6780 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6781 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006782
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006783 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006784 eir_len = eir_append_data(ev->eir, eir_len,
6785 EIR_CLASS_OF_DEV,
6786 conn->dev_class, 3);
6787 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006788
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006789 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006790
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006791 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6792 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006793}
6794
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006795static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006796{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006797 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006798
Johan Hedbergf5818c22014-12-05 13:36:02 +02006799 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006800
6801 *sk = cmd->sk;
6802 sock_hold(*sk);
6803
Johan Hedberga664b5b2011-02-19 12:06:02 -03006804 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006805}
6806
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006807static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006808{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006809 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006810 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006811
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006812 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6813
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006814 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006815 mgmt_pending_remove(cmd);
6816}
6817
Johan Hedberg84c61d92014-08-01 11:13:30 +03006818bool mgmt_powering_down(struct hci_dev *hdev)
6819{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006820 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006821 struct mgmt_mode *cp;
6822
6823 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6824 if (!cmd)
6825 return false;
6826
6827 cp = cmd->param;
6828 if (!cp->val)
6829 return true;
6830
6831 return false;
6832}
6833
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006834void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006835 u8 link_type, u8 addr_type, u8 reason,
6836 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006837{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006838 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006839 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006840
Johan Hedberg84c61d92014-08-01 11:13:30 +03006841 /* The connection is still in hci_conn_hash so test for 1
6842 * instead of 0 to know if this is the last one.
6843 */
6844 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6845 cancel_delayed_work(&hdev->power_off);
6846 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006847 }
6848
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006849 if (!mgmt_connected)
6850 return;
6851
Andre Guedes57eb7762013-10-30 19:01:41 -03006852 if (link_type != ACL_LINK && link_type != LE_LINK)
6853 return;
6854
Johan Hedberg744cf192011-11-08 20:40:14 +02006855 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006856
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006857 bacpy(&ev.addr.bdaddr, bdaddr);
6858 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6859 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006860
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006861 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006862
6863 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006864 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006865
Johan Hedberg124f6e32012-02-09 13:50:12 +02006866 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006867 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006868}
6869
Marcel Holtmann78929242013-10-06 23:55:47 -07006870void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6871 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006872{
Andre Guedes3655bba2013-10-30 19:01:40 -03006873 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6874 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006875 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006876
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006877 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6878 hdev);
6879
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006880 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006881 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006882 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006883
Andre Guedes3655bba2013-10-30 19:01:40 -03006884 cp = cmd->param;
6885
6886 if (bacmp(bdaddr, &cp->addr.bdaddr))
6887 return;
6888
6889 if (cp->addr.type != bdaddr_type)
6890 return;
6891
Johan Hedbergf5818c22014-12-05 13:36:02 +02006892 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006893 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006894}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006895
Marcel Holtmann445608d2013-10-06 23:55:48 -07006896void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6897 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006898{
6899 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006900
Johan Hedberg84c61d92014-08-01 11:13:30 +03006901 /* The connection is still in hci_conn_hash so test for 1
6902 * instead of 0 to know if this is the last one.
6903 */
6904 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6905 cancel_delayed_work(&hdev->power_off);
6906 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006907 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006908
Johan Hedberg4c659c32011-11-07 23:13:39 +02006909 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006910 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006911 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006912
Marcel Holtmann445608d2013-10-06 23:55:48 -07006913 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006914}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006915
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006916void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006917{
6918 struct mgmt_ev_pin_code_request ev;
6919
Johan Hedbergd8457692012-02-17 14:24:57 +02006920 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006921 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006922 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006923
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006924 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006925}
6926
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006927void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6928 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006929{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006930 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006931
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006932 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006933 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006934 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006935
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006936 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006937 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006938}
6939
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006940void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6941 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006942{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006943 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006944
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006945 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006946 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006947 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006948
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006949 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006950 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006951}
Johan Hedberga5c29682011-02-19 12:05:57 -03006952
Johan Hedberg744cf192011-11-08 20:40:14 +02006953int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006954 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006955 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006956{
6957 struct mgmt_ev_user_confirm_request ev;
6958
Johan Hedberg744cf192011-11-08 20:40:14 +02006959 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006960
Johan Hedberg272d90d2012-02-09 15:26:12 +02006961 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006962 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006963 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006964 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006965
Johan Hedberg744cf192011-11-08 20:40:14 +02006966 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006967 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006968}
6969
Johan Hedberg272d90d2012-02-09 15:26:12 +02006970int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006971 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006972{
6973 struct mgmt_ev_user_passkey_request ev;
6974
6975 BT_DBG("%s", hdev->name);
6976
Johan Hedberg272d90d2012-02-09 15:26:12 +02006977 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006978 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006979
6980 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006981 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006982}
6983
Brian Gix0df4c182011-11-16 13:53:13 -08006984static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006985 u8 link_type, u8 addr_type, u8 status,
6986 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006987{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006988 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006989
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006990 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006991 if (!cmd)
6992 return -ENOENT;
6993
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006994 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006995 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006996
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006997 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006998}
6999
Johan Hedberg744cf192011-11-08 20:40:14 +02007000int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007001 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007002{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007003 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007004 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007005}
7006
Johan Hedberg272d90d2012-02-09 15:26:12 +02007007int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007008 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007009{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007010 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007011 status,
7012 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007013}
Johan Hedberg2a611692011-02-19 12:06:00 -03007014
Brian Gix604086b2011-11-23 08:28:33 -08007015int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007016 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007017{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007018 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007019 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007020}
7021
Johan Hedberg272d90d2012-02-09 15:26:12 +02007022int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007023 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007024{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007025 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007026 status,
7027 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007028}
7029
Johan Hedberg92a25252012-09-06 18:39:26 +03007030int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7031 u8 link_type, u8 addr_type, u32 passkey,
7032 u8 entered)
7033{
7034 struct mgmt_ev_passkey_notify ev;
7035
7036 BT_DBG("%s", hdev->name);
7037
7038 bacpy(&ev.addr.bdaddr, bdaddr);
7039 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7040 ev.passkey = __cpu_to_le32(passkey);
7041 ev.entered = entered;
7042
7043 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7044}
7045
Johan Hedberge1e930f2014-09-08 17:09:49 -07007046void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007047{
7048 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007049 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007050 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007051
Johan Hedberge1e930f2014-09-08 17:09:49 -07007052 bacpy(&ev.addr.bdaddr, &conn->dst);
7053 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7054 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007055
Johan Hedberge1e930f2014-09-08 17:09:49 -07007056 cmd = find_pairing(conn);
7057
7058 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7059 cmd ? cmd->sk : NULL);
7060
Johan Hedberga511b352014-12-11 21:45:45 +02007061 if (cmd) {
7062 cmd->cmd_complete(cmd, status);
7063 mgmt_pending_remove(cmd);
7064 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007065}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007066
Marcel Holtmann464996a2013-10-15 14:26:24 -07007067void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007068{
7069 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007070 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007071
7072 if (status) {
7073 u8 mgmt_err = mgmt_status(status);
7074 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007075 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007076 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007077 }
7078
Marcel Holtmann464996a2013-10-15 14:26:24 -07007079 if (test_bit(HCI_AUTH, &hdev->flags))
7080 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7081 &hdev->dev_flags);
7082 else
7083 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7084 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007085
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007086 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007087 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007088
Johan Hedberg47990ea2012-02-22 11:58:37 +02007089 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007090 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007091
7092 if (match.sk)
7093 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007094}
7095
Johan Hedberg890ea892013-03-15 17:06:52 -05007096static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007097{
Johan Hedberg890ea892013-03-15 17:06:52 -05007098 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007099 struct hci_cp_write_eir cp;
7100
Johan Hedberg976eb202012-10-24 21:12:01 +03007101 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007102 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007103
Johan Hedbergc80da272012-02-22 15:38:48 +02007104 memset(hdev->eir, 0, sizeof(hdev->eir));
7105
Johan Hedbergcacaf522012-02-21 00:52:42 +02007106 memset(&cp, 0, sizeof(cp));
7107
Johan Hedberg890ea892013-03-15 17:06:52 -05007108 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007109}
7110
Marcel Holtmann3e248562013-10-15 14:26:25 -07007111void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007112{
7113 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007114 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007115 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007116
7117 if (status) {
7118 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007119
7120 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007121 &hdev->dev_flags)) {
7122 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007123 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007124 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007125
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007126 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7127 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007128 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007129 }
7130
7131 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007132 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007133 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007134 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7135 if (!changed)
7136 changed = test_and_clear_bit(HCI_HS_ENABLED,
7137 &hdev->dev_flags);
7138 else
7139 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007140 }
7141
7142 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7143
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007144 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007145 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007146
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007147 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007148 sock_put(match.sk);
7149
Johan Hedberg890ea892013-03-15 17:06:52 -05007150 hci_req_init(&req, hdev);
7151
Johan Hedberg37699722014-06-24 14:00:27 +03007152 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
7153 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
7154 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7155 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007156 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007157 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007158 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007159 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007160
7161 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007162}
7163
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007164static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007165{
7166 struct cmd_lookup *match = data;
7167
Johan Hedberg90e70452012-02-23 23:09:40 +02007168 if (match->sk == NULL) {
7169 match->sk = cmd->sk;
7170 sock_hold(match->sk);
7171 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007172}
7173
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007174void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7175 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007176{
Johan Hedberg90e70452012-02-23 23:09:40 +02007177 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007178
Johan Hedberg92da6092013-03-15 17:06:55 -05007179 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7180 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7181 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007182
7183 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007184 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7185 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007186
7187 if (match.sk)
7188 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007189}
7190
Marcel Holtmann7667da32013-10-15 14:26:27 -07007191void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007192{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007193 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007194 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007195
Johan Hedberg13928972013-03-15 17:07:00 -05007196 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007197 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007198
7199 memset(&ev, 0, sizeof(ev));
7200 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007201 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007202
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007203 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007204 if (!cmd) {
7205 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007206
Johan Hedberg13928972013-03-15 17:07:00 -05007207 /* If this is a HCI command related to powering on the
7208 * HCI dev don't send any mgmt signals.
7209 */
7210 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007211 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007212 }
7213
Marcel Holtmann7667da32013-10-15 14:26:27 -07007214 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7215 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007216}
Szymon Jancc35938b2011-03-22 13:12:21 +01007217
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007218void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007219 u8 *rand192, u8 *hash256, u8 *rand256,
7220 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007221{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007222 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007223
Johan Hedberg744cf192011-11-08 20:40:14 +02007224 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007225
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007226 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007227 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007228 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007229
7230 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007231 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7232 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007233 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007234 struct mgmt_rp_read_local_oob_data rp;
7235 size_t rp_size = sizeof(rp);
7236
7237 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7238 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7239
Johan Hedberg710f11c2014-05-26 11:21:22 +03007240 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007241 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007242 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007243 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007244 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007245 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007246
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007247 mgmt_cmd_complete(cmd->sk, hdev->id,
7248 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7249 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007250 }
7251
7252 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007253}
Johan Hedberge17acd42011-03-30 23:57:16 +03007254
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007255static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7256{
7257 int i;
7258
7259 for (i = 0; i < uuid_count; i++) {
7260 if (!memcmp(uuid, uuids[i], 16))
7261 return true;
7262 }
7263
7264 return false;
7265}
7266
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007267static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7268{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007269 u16 parsed = 0;
7270
7271 while (parsed < eir_len) {
7272 u8 field_len = eir[0];
7273 u8 uuid[16];
7274 int i;
7275
7276 if (field_len == 0)
7277 break;
7278
7279 if (eir_len - parsed < field_len + 1)
7280 break;
7281
7282 switch (eir[1]) {
7283 case EIR_UUID16_ALL:
7284 case EIR_UUID16_SOME:
7285 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007286 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007287 uuid[13] = eir[i + 3];
7288 uuid[12] = eir[i + 2];
7289 if (has_uuid(uuid, uuid_count, uuids))
7290 return true;
7291 }
7292 break;
7293 case EIR_UUID32_ALL:
7294 case EIR_UUID32_SOME:
7295 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007296 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007297 uuid[15] = eir[i + 5];
7298 uuid[14] = eir[i + 4];
7299 uuid[13] = eir[i + 3];
7300 uuid[12] = eir[i + 2];
7301 if (has_uuid(uuid, uuid_count, uuids))
7302 return true;
7303 }
7304 break;
7305 case EIR_UUID128_ALL:
7306 case EIR_UUID128_SOME:
7307 for (i = 0; i + 17 <= field_len; i += 16) {
7308 memcpy(uuid, eir + i + 2, 16);
7309 if (has_uuid(uuid, uuid_count, uuids))
7310 return true;
7311 }
7312 break;
7313 }
7314
7315 parsed += field_len + 1;
7316 eir += field_len + 1;
7317 }
7318
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007319 return false;
7320}
7321
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007322static void restart_le_scan(struct hci_dev *hdev)
7323{
7324 /* If controller is not scanning we are done. */
7325 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7326 return;
7327
7328 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7329 hdev->discovery.scan_start +
7330 hdev->discovery.scan_duration))
7331 return;
7332
7333 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7334 DISCOV_LE_RESTART_DELAY);
7335}
7336
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007337static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7338 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7339{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007340 /* If a RSSI threshold has been specified, and
7341 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7342 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7343 * is set, let it through for further processing, as we might need to
7344 * restart the scan.
7345 *
7346 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7347 * the results are also dropped.
7348 */
7349 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7350 (rssi == HCI_RSSI_INVALID ||
7351 (rssi < hdev->discovery.rssi &&
7352 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7353 return false;
7354
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007355 if (hdev->discovery.uuid_count != 0) {
7356 /* If a list of UUIDs is provided in filter, results with no
7357 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007358 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007359 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7360 hdev->discovery.uuids) &&
7361 !eir_has_uuids(scan_rsp, scan_rsp_len,
7362 hdev->discovery.uuid_count,
7363 hdev->discovery.uuids))
7364 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007365 }
7366
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007367 /* If duplicate filtering does not report RSSI changes, then restart
7368 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007369 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007370 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7371 restart_le_scan(hdev);
7372
7373 /* Validate RSSI value against the RSSI threshold once more. */
7374 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7375 rssi < hdev->discovery.rssi)
7376 return false;
7377 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007378
7379 return true;
7380}
7381
Marcel Holtmann901801b2013-10-06 23:55:51 -07007382void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007383 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7384 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007385{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007386 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007387 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007388 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007389
Johan Hedberg75ce2082014-07-02 22:42:01 +03007390 /* Don't send events for a non-kernel initiated discovery. With
7391 * LE one exception is if we have pend_le_reports > 0 in which
7392 * case we're doing passive scanning and want these events.
7393 */
7394 if (!hci_discovery_active(hdev)) {
7395 if (link_type == ACL_LINK)
7396 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007397 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007398 return;
7399 }
Andre Guedes12602d02013-04-30 15:29:40 -03007400
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007401 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007402 /* We are using service discovery */
7403 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7404 scan_rsp_len))
7405 return;
7406 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007407
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007408 /* Make sure that the buffer is big enough. The 5 extra bytes
7409 * are for the potential CoD field.
7410 */
7411 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007412 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007413
Johan Hedberg1dc06092012-01-15 21:01:23 +02007414 memset(buf, 0, sizeof(buf));
7415
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007416 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7417 * RSSI value was reported as 0 when not available. This behavior
7418 * is kept when using device discovery. This is required for full
7419 * backwards compatibility with the API.
7420 *
7421 * However when using service discovery, the value 127 will be
7422 * returned when the RSSI is not available.
7423 */
Szymon Janc91200e92015-01-22 16:57:05 +01007424 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7425 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007426 rssi = 0;
7427
Johan Hedberg841c5642014-07-07 12:45:54 +03007428 bacpy(&ev->addr.bdaddr, bdaddr);
7429 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007430 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007431 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007432
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007433 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007434 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007435 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007436
Johan Hedberg1dc06092012-01-15 21:01:23 +02007437 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7438 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007439 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007440
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007441 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007442 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007443 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007444
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007445 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7446 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007447
Marcel Holtmann901801b2013-10-06 23:55:51 -07007448 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007449}
Johan Hedberga88a9652011-03-30 13:18:12 +03007450
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007451void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7452 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007453{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007454 struct mgmt_ev_device_found *ev;
7455 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7456 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007457
Johan Hedbergb644ba32012-01-17 21:48:47 +02007458 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007459
Johan Hedbergb644ba32012-01-17 21:48:47 +02007460 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007461
Johan Hedbergb644ba32012-01-17 21:48:47 +02007462 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007463 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007464 ev->rssi = rssi;
7465
7466 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007467 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007468
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007469 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007470
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007471 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007472}
Johan Hedberg314b2382011-04-27 10:29:57 -04007473
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007474void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007475{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007476 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007477
Andre Guedes343fb142011-11-22 17:14:19 -03007478 BT_DBG("%s discovering %u", hdev->name, discovering);
7479
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007480 memset(&ev, 0, sizeof(ev));
7481 ev.type = hdev->discovery.type;
7482 ev.discovering = discovering;
7483
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007484 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007485}
Antti Julku5e762442011-08-25 16:48:02 +03007486
Marcel Holtmann1904a852015-01-11 13:50:44 -08007487static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007488{
7489 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007490}
7491
7492void mgmt_reenable_advertising(struct hci_dev *hdev)
7493{
7494 struct hci_request req;
7495
Marcel Holtmann5976e602013-10-06 04:08:14 -07007496 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7497 return;
7498
7499 hci_req_init(&req, hdev);
7500 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007501 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007502}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007503
7504static struct hci_mgmt_chan chan = {
7505 .channel = HCI_CHANNEL_CONTROL,
7506 .handler_count = ARRAY_SIZE(mgmt_handlers),
7507 .handlers = mgmt_handlers,
7508};
7509
7510int mgmt_init(void)
7511{
7512 return hci_mgmt_chan_register(&chan);
7513}
7514
7515void mgmt_exit(void)
7516{
7517 hci_mgmt_chan_unregister(&chan);
7518}