blob: d769b428b630672620015ef359d55e92276a6399 [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 Hedbergf7b64e692010-12-13 21:07:06 +0200261{
262 struct sk_buff *skb;
263 struct mgmt_hdr *hdr;
264 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300265 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200266
Szymon Janc34eb5252011-02-28 14:10:08 +0100267 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200268
Andre Guedes790eff42012-06-07 19:05:46 -0300269 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200270 if (!skb)
271 return -ENOMEM;
272
273 hdr = (void *) skb_put(skb, sizeof(*hdr));
274
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100276 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200277 hdr->len = cpu_to_le16(sizeof(*ev));
278
279 ev = (void *) skb_put(skb, sizeof(*ev));
280 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200281 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200282
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 err = sock_queue_rcv_skb(sk, skb);
284 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200285 kfree_skb(skb);
286
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300287 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200288}
289
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200290static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
291 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200292{
293 struct sk_buff *skb;
294 struct mgmt_hdr *hdr;
295 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300296 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200297
298 BT_DBG("sock %p", sk);
299
Andre Guedes790eff42012-06-07 19:05:46 -0300300 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200301 if (!skb)
302 return -ENOMEM;
303
304 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200305
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700306 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100307 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200308 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200309
Johan Hedberga38528f2011-01-22 06:46:43 +0200310 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200311 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200312 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100313
314 if (rp)
315 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200316
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300317 err = sock_queue_rcv_skb(sk, skb);
318 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200319 kfree_skb(skb);
320
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100321 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200322}
323
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300324static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
325 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200326{
327 struct mgmt_rp_read_version rp;
328
329 BT_DBG("sock %p", sk);
330
331 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700332 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200333
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200334 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
335 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200336}
337
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300338static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
339 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200340{
341 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200342 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
343 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200344 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345 size_t rp_size;
346 int i, err;
347
348 BT_DBG("sock %p", sk);
349
350 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
351
352 rp = kmalloc(rp_size, GFP_KERNEL);
353 if (!rp)
354 return -ENOMEM;
355
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700356 rp->num_commands = cpu_to_le16(num_commands);
357 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200358
359 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
360 put_unaligned_le16(mgmt_commands[i], opcode);
361
362 for (i = 0; i < num_events; i++, opcode++)
363 put_unaligned_le16(mgmt_events[i], opcode);
364
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200365 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
366 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200367 kfree(rp);
368
369 return err;
370}
371
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300372static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
373 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200376 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200377 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200378 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300379 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200380
381 BT_DBG("sock %p", sk);
382
383 read_lock(&hci_dev_list_lock);
384
385 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300386 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200387 if (d->dev_type == HCI_BREDR &&
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 Holtmannd603b76b2014-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 Holtmannd603b76b2014-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 Hedbergf7b64e692010-12-13 21:07:06 +0200596
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200597 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
598 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200599 settings |= MGMT_SETTING_CONFIGURATION;
600
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200601 return settings;
602}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200603
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604static u32 get_current_settings(struct hci_dev *hdev)
605{
606 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200607
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200608 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100609 settings |= MGMT_SETTING_POWERED;
610
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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200631
Johan Hedberg84bde9d6c2012-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 Hedbergf7b64e692010-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 Hedberg84bde9d6c2012-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 Hedbergf7b64e692010-12-13 21:07:06 +02001644
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001645 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +02001771 if (err < 0)
1772 mgmt_pending_remove(cmd);
1773
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001774failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001775 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-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 Hedberge8ba3a1f2013-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 Hedberge8ba3a1f2013-10-19 23:38:18 +03001887 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001888 }
Johan Hedberge8ba3a1f2013-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedberge8ba3a1f2013-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 Hedberg4c01f8b2013-03-15 17:07:14 -05001971 /* If we're going from non-connectable to connectable or
1972 * vice-versa when fast connectable is enabled ensure that fast
1973 * connectable gets disabled. write_fast_connectable won't do
1974 * anything if the page scan parameters are already what they
1975 * should be.
1976 */
1977 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001978 write_fast_connectable(&req, false);
1979
Johan Hedberge8b12022014-07-10 10:51:27 +03001980 /* Update the advertising parameters if necessary */
1981 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001982 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001983
Johan Hedberg2b76f452013-03-15 17:07:04 -05001984 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001985 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001987 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001988 err = set_connectable_update_settings(hdev, sk,
1989 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001990 goto failed;
1991 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992
1993failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001994 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001995 return err;
1996}
1997
Johan Hedbergb2939472014-07-30 09:22:23 +03001998static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001999 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002000{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002001 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002002 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002003 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002004
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002005 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002006
Johan Hedberga7e80f22013-01-09 16:05:19 +02002007 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002008 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2009 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002010
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002011 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002012
2013 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002014 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002015 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002016 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002017
Johan Hedbergb2939472014-07-30 09:22:23 +03002018 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002019 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002020 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002021
Marcel Holtmann55594352013-10-06 16:11:57 -07002022 if (changed)
2023 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002024
Marcel Holtmann55594352013-10-06 16:11:57 -07002025unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002026 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002027 return err;
2028}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002029
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002030static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2031 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032{
2033 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002034 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002035 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002036 int err;
2037
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002038 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002039
Johan Hedberge6fe7982013-10-02 15:45:22 +03002040 status = mgmt_bredr_support(hdev);
2041 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002042 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2043 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002044
Johan Hedberga7e80f22013-01-09 16:05:19 +02002045 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002046 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2047 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002048
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002049 hci_dev_lock(hdev);
2050
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002051 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002052 bool changed = false;
2053
2054 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002055 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002056 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2057 changed = true;
2058 }
2059
2060 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2061 if (err < 0)
2062 goto failed;
2063
2064 if (changed)
2065 err = new_settings(hdev, sk);
2066
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002067 goto failed;
2068 }
2069
2070 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002071 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2072 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002073 goto failed;
2074 }
2075
2076 val = !!cp->val;
2077
2078 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2079 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2080 goto failed;
2081 }
2082
2083 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2084 if (!cmd) {
2085 err = -ENOMEM;
2086 goto failed;
2087 }
2088
2089 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2090 if (err < 0) {
2091 mgmt_pending_remove(cmd);
2092 goto failed;
2093 }
2094
2095failed:
2096 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002097 return err;
2098}
2099
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002100static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002101{
2102 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002103 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002104 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002105 int err;
2106
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002107 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002108
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002109 status = mgmt_bredr_support(hdev);
2110 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002111 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002112
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002113 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002114 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2115 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002116
Johan Hedberga7e80f22013-01-09 16:05:19 +02002117 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002118 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2119 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002120
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002121 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002122
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002123 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002124 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002125
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002126 if (cp->val) {
2127 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2128 &hdev->dev_flags);
2129 } else {
2130 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2131 &hdev->dev_flags);
2132 if (!changed)
2133 changed = test_and_clear_bit(HCI_HS_ENABLED,
2134 &hdev->dev_flags);
2135 else
2136 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002137 }
2138
2139 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2140 if (err < 0)
2141 goto failed;
2142
2143 if (changed)
2144 err = new_settings(hdev, sk);
2145
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002146 goto failed;
2147 }
2148
Johan Hedberg94d52da2015-02-19 17:38:06 +02002149 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002150 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2151 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002152 goto failed;
2153 }
2154
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002155 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002156 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2157 goto failed;
2158 }
2159
2160 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2161 if (!cmd) {
2162 err = -ENOMEM;
2163 goto failed;
2164 }
2165
Johan Hedberg37699722014-06-24 14:00:27 +03002166 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2167 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2168 sizeof(cp->val), &cp->val);
2169
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002170 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002171 if (err < 0) {
2172 mgmt_pending_remove(cmd);
2173 goto failed;
2174 }
2175
2176failed:
2177 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002178 return err;
2179}
2180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002181static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002182{
2183 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002184 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002185 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002186 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002188 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002189
Johan Hedberge6fe7982013-10-02 15:45:22 +03002190 status = mgmt_bredr_support(hdev);
2191 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002192 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002193
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002194 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002195 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2196 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002197
2198 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002199 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2200 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002201
Johan Hedberga7e80f22013-01-09 16:05:19 +02002202 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002203 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2204 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002205
Marcel Holtmannee392692013-10-01 22:59:23 -07002206 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002207
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002208 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002209 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2210 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002211 goto unlock;
2212 }
2213
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002214 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002215 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002216 } else {
2217 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002218 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2219 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002220 goto unlock;
2221 }
2222
Marcel Holtmannee392692013-10-01 22:59:23 -07002223 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002224 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002225
2226 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2227 if (err < 0)
2228 goto unlock;
2229
2230 if (changed)
2231 err = new_settings(hdev, sk);
2232
2233unlock:
2234 hci_dev_unlock(hdev);
2235 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002236}
2237
Marcel Holtmann1904a852015-01-11 13:50:44 -08002238static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002239{
2240 struct cmd_lookup match = { NULL, hdev };
2241
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302242 hci_dev_lock(hdev);
2243
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002244 if (status) {
2245 u8 mgmt_err = mgmt_status(status);
2246
2247 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2248 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302249 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002250 }
2251
2252 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2253
2254 new_settings(hdev, match.sk);
2255
2256 if (match.sk)
2257 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002258
2259 /* Make sure the controller has a good default for
2260 * advertising data. Restrict the update to when LE
2261 * has actually been enabled. During power on, the
2262 * update in powered_update_hci will take care of it.
2263 */
2264 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2265 struct hci_request req;
2266
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002267 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002268 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002269 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002270 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002271 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002272 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302273
2274unlock:
2275 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002276}
2277
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002278static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002279{
2280 struct mgmt_mode *cp = data;
2281 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002282 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002283 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002284 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002285 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002286
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002287 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002288
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002289 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002290 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2291 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002292
Johan Hedberga7e80f22013-01-09 16:05:19 +02002293 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002294 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2295 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002296
Johan Hedbergc73eee92013-04-19 18:35:21 +03002297 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002298 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002299 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2300 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002301
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002302 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002303
2304 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002305 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002306
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002307 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002308 bool changed = false;
2309
2310 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2311 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2312 changed = true;
2313 }
2314
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002315 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2316 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002317 changed = true;
2318 }
2319
Johan Hedberg06199cf2012-02-22 16:37:11 +02002320 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2321 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002322 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002323
2324 if (changed)
2325 err = new_settings(hdev, sk);
2326
Johan Hedberg1de028c2012-02-29 19:55:35 -08002327 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002328 }
2329
Johan Hedberg4375f102013-09-25 13:26:10 +03002330 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2331 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002332 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2333 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002334 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002335 }
2336
2337 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2338 if (!cmd) {
2339 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002340 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002341 }
2342
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002343 hci_req_init(&req, hdev);
2344
Johan Hedberg06199cf2012-02-22 16:37:11 +02002345 memset(&hci_cp, 0, sizeof(hci_cp));
2346
2347 if (val) {
2348 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002349 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002350 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002351 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002352 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002353 }
2354
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002355 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2356 &hci_cp);
2357
2358 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302359 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002360 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002361
Johan Hedberg1de028c2012-02-29 19:55:35 -08002362unlock:
2363 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002364 return err;
2365}
2366
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002367/* This is a helper function to test for pending mgmt commands that can
2368 * cause CoD or EIR HCI commands. We can only allow one such pending
2369 * mgmt command at a time since otherwise we cannot easily track what
2370 * the current values are, will be, and based on that calculate if a new
2371 * HCI command needs to be sent and if yes with what value.
2372 */
2373static bool pending_eir_or_class(struct hci_dev *hdev)
2374{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002375 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002376
2377 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2378 switch (cmd->opcode) {
2379 case MGMT_OP_ADD_UUID:
2380 case MGMT_OP_REMOVE_UUID:
2381 case MGMT_OP_SET_DEV_CLASS:
2382 case MGMT_OP_SET_POWERED:
2383 return true;
2384 }
2385 }
2386
2387 return false;
2388}
2389
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002390static const u8 bluetooth_base_uuid[] = {
2391 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2392 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2393};
2394
2395static u8 get_uuid_size(const u8 *uuid)
2396{
2397 u32 val;
2398
2399 if (memcmp(uuid, bluetooth_base_uuid, 12))
2400 return 128;
2401
2402 val = get_unaligned_le32(&uuid[12]);
2403 if (val > 0xffff)
2404 return 32;
2405
2406 return 16;
2407}
2408
Johan Hedberg92da6092013-03-15 17:06:55 -05002409static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2410{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002411 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002412
2413 hci_dev_lock(hdev);
2414
2415 cmd = mgmt_pending_find(mgmt_op, hdev);
2416 if (!cmd)
2417 goto unlock;
2418
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002419 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2420 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002421
2422 mgmt_pending_remove(cmd);
2423
2424unlock:
2425 hci_dev_unlock(hdev);
2426}
2427
Marcel Holtmann1904a852015-01-11 13:50:44 -08002428static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002429{
2430 BT_DBG("status 0x%02x", status);
2431
2432 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2433}
2434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002435static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002436{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002437 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002438 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002439 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002440 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002441 int err;
2442
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002443 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002444
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002445 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002446
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002447 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002448 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2449 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002450 goto failed;
2451 }
2452
Andre Guedes92c4c202012-06-07 19:05:44 -03002453 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002454 if (!uuid) {
2455 err = -ENOMEM;
2456 goto failed;
2457 }
2458
2459 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002460 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002461 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002462
Johan Hedbergde66aa62013-01-27 00:31:27 +02002463 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002464
Johan Hedberg890ea892013-03-15 17:06:52 -05002465 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002466
Johan Hedberg890ea892013-03-15 17:06:52 -05002467 update_class(&req);
2468 update_eir(&req);
2469
Johan Hedberg92da6092013-03-15 17:06:55 -05002470 err = hci_req_run(&req, add_uuid_complete);
2471 if (err < 0) {
2472 if (err != -ENODATA)
2473 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002474
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002475 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2476 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002477 goto failed;
2478 }
2479
2480 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002481 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002482 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002483 goto failed;
2484 }
2485
2486 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487
2488failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002489 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002490 return err;
2491}
2492
Johan Hedberg24b78d02012-02-23 23:24:30 +02002493static bool enable_service_cache(struct hci_dev *hdev)
2494{
2495 if (!hdev_is_powered(hdev))
2496 return false;
2497
2498 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002499 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2500 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002501 return true;
2502 }
2503
2504 return false;
2505}
2506
Marcel Holtmann1904a852015-01-11 13:50:44 -08002507static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002508{
2509 BT_DBG("status 0x%02x", status);
2510
2511 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2512}
2513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002514static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002515 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002516{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002517 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002518 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002519 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 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 -05002521 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002522 int err, found;
2523
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002524 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002525
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002526 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002527
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002528 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002529 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2530 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002531 goto unlock;
2532 }
2533
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002534 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002535 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002536
Johan Hedberg24b78d02012-02-23 23:24:30 +02002537 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002538 err = mgmt_cmd_complete(sk, hdev->id,
2539 MGMT_OP_REMOVE_UUID,
2540 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002541 goto unlock;
2542 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002543
Johan Hedberg9246a862012-02-23 21:33:16 +02002544 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002545 }
2546
2547 found = 0;
2548
Johan Hedberg056341c2013-01-27 00:31:30 +02002549 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002550 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2551 continue;
2552
2553 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002554 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002555 found++;
2556 }
2557
2558 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002559 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2560 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002561 goto unlock;
2562 }
2563
Johan Hedberg9246a862012-02-23 21:33:16 +02002564update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002565 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002566
Johan Hedberg890ea892013-03-15 17:06:52 -05002567 update_class(&req);
2568 update_eir(&req);
2569
Johan Hedberg92da6092013-03-15 17:06:55 -05002570 err = hci_req_run(&req, remove_uuid_complete);
2571 if (err < 0) {
2572 if (err != -ENODATA)
2573 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002574
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002575 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2576 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002577 goto unlock;
2578 }
2579
2580 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002581 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002582 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002583 goto unlock;
2584 }
2585
2586 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002587
2588unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002589 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002590 return err;
2591}
2592
Marcel Holtmann1904a852015-01-11 13:50:44 -08002593static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002594{
2595 BT_DBG("status 0x%02x", status);
2596
2597 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2598}
2599
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002600static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002601 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002602{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002603 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002604 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002605 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002606 int err;
2607
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002608 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002609
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002610 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002611 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2612 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002613
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002614 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002615
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002616 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002617 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2618 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002619 goto unlock;
2620 }
2621
2622 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002623 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2624 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002625 goto unlock;
2626 }
2627
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002628 hdev->major_class = cp->major;
2629 hdev->minor_class = cp->minor;
2630
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002631 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002632 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2633 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002634 goto unlock;
2635 }
2636
Johan Hedberg890ea892013-03-15 17:06:52 -05002637 hci_req_init(&req, hdev);
2638
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002639 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002640 hci_dev_unlock(hdev);
2641 cancel_delayed_work_sync(&hdev->service_cache);
2642 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002643 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002644 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002645
Johan Hedberg890ea892013-03-15 17:06:52 -05002646 update_class(&req);
2647
Johan Hedberg92da6092013-03-15 17:06:55 -05002648 err = hci_req_run(&req, set_class_complete);
2649 if (err < 0) {
2650 if (err != -ENODATA)
2651 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002652
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002653 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2654 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002655 goto unlock;
2656 }
2657
2658 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002659 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002660 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002661 goto unlock;
2662 }
2663
2664 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002665
Johan Hedbergb5235a62012-02-21 14:32:24 +02002666unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002667 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002668 return err;
2669}
2670
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002671static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002672 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002673{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002674 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002675 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2676 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002677 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002678 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002679 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002680
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002681 BT_DBG("request for %s", hdev->name);
2682
2683 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002684 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2685 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002686
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002687 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002688 if (key_count > max_key_count) {
2689 BT_ERR("load_link_keys: too big key_count value %u",
2690 key_count);
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 Hedbergba1d6932014-07-03 13:52:27 +03002693 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694
Johan Hedberg86742e12011-11-07 23:13:38 +02002695 expected_len = sizeof(*cp) + key_count *
2696 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002697 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002698 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002699 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002700 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2701 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702 }
2703
Johan Hedberg4ae14302013-01-20 14:27:13 +02002704 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002705 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2706 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002707
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002708 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002709 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002711 for (i = 0; i < key_count; i++) {
2712 struct mgmt_link_key_info *key = &cp->keys[i];
2713
Marcel Holtmann8e991132014-01-10 02:07:25 -08002714 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002715 return mgmt_cmd_status(sk, hdev->id,
2716 MGMT_OP_LOAD_LINK_KEYS,
2717 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002718 }
2719
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002720 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002721
2722 hci_link_keys_clear(hdev);
2723
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002724 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002725 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2726 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002727 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002728 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2729 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002730
2731 if (changed)
2732 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002733
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002734 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002735 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002736
Johan Hedberg58e92932014-06-24 14:00:26 +03002737 /* Always ignore debug keys and require a new pairing if
2738 * the user wants to use them.
2739 */
2740 if (key->type == HCI_LK_DEBUG_COMBINATION)
2741 continue;
2742
Johan Hedberg7652ff62014-06-24 13:15:49 +03002743 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2744 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002745 }
2746
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002747 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002748
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002749 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002750
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002751 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002752}
2753
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002754static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002755 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002756{
2757 struct mgmt_ev_device_unpaired ev;
2758
2759 bacpy(&ev.addr.bdaddr, bdaddr);
2760 ev.addr.type = addr_type;
2761
2762 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002763 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002764}
2765
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002766static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002767 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002768{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002769 struct mgmt_cp_unpair_device *cp = data;
2770 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002771 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002772 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002773 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002774 int err;
2775
Johan Hedberga8a1d192011-11-10 15:54:38 +02002776 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002777 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2778 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002779
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002780 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002781 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2782 MGMT_STATUS_INVALID_PARAMS,
2783 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002784
Johan Hedberg118da702013-01-20 14:27:20 +02002785 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002786 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2787 MGMT_STATUS_INVALID_PARAMS,
2788 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002789
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002790 hci_dev_lock(hdev);
2791
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002792 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002793 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2794 MGMT_STATUS_NOT_POWERED, &rp,
2795 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002796 goto unlock;
2797 }
2798
Johan Hedberge0b2b272014-02-18 17:14:31 +02002799 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002800 /* If disconnection is requested, then look up the
2801 * connection. If the remote device is connected, it
2802 * will be later used to terminate the link.
2803 *
2804 * Setting it to NULL explicitly will cause no
2805 * termination of the link.
2806 */
2807 if (cp->disconnect)
2808 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2809 &cp->addr.bdaddr);
2810 else
2811 conn = NULL;
2812
Johan Hedberg124f6e32012-02-09 13:50:12 +02002813 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002814 } else {
2815 u8 addr_type;
2816
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002817 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2818 &cp->addr.bdaddr);
2819 if (conn) {
2820 /* Defer clearing up the connection parameters
2821 * until closing to give a chance of keeping
2822 * them if a repairing happens.
2823 */
2824 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2825
2826 /* If disconnection is not requested, then
2827 * clear the connection variable so that the
2828 * link is not terminated.
2829 */
2830 if (!cp->disconnect)
2831 conn = NULL;
2832 }
2833
Johan Hedberge0b2b272014-02-18 17:14:31 +02002834 if (cp->addr.type == BDADDR_LE_PUBLIC)
2835 addr_type = ADDR_LE_DEV_PUBLIC;
2836 else
2837 addr_type = ADDR_LE_DEV_RANDOM;
2838
Johan Hedberga7ec7332014-02-18 17:14:35 +02002839 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2840
Johan Hedberge0b2b272014-02-18 17:14:31 +02002841 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2842 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002843
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002844 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002845 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2846 MGMT_STATUS_NOT_PAIRED, &rp,
2847 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002848 goto unlock;
2849 }
2850
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002851 /* If the connection variable is set, then termination of the
2852 * link is requested.
2853 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002854 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002855 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2856 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002857 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002858 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002859 }
2860
Johan Hedberg124f6e32012-02-09 13:50:12 +02002861 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002862 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002863 if (!cmd) {
2864 err = -ENOMEM;
2865 goto unlock;
2866 }
2867
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002868 cmd->cmd_complete = addr_cmd_complete;
2869
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002870 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002871 dc.reason = 0x13; /* Remote User Terminated Connection */
2872 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2873 if (err < 0)
2874 mgmt_pending_remove(cmd);
2875
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002876unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002877 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002878 return err;
2879}
2880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002881static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002882 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002883{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002884 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002885 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002886 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002887 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002888 int err;
2889
2890 BT_DBG("");
2891
Johan Hedberg06a63b12013-01-20 14:27:21 +02002892 memset(&rp, 0, sizeof(rp));
2893 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2894 rp.addr.type = cp->addr.type;
2895
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002896 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002897 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2898 MGMT_STATUS_INVALID_PARAMS,
2899 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002900
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002901 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002902
2903 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002904 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2905 MGMT_STATUS_NOT_POWERED, &rp,
2906 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002907 goto failed;
2908 }
2909
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002910 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002911 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2912 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002913 goto failed;
2914 }
2915
Andre Guedes591f47f2012-04-24 21:02:49 -03002916 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002917 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2918 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002919 else
2920 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002921
Vishal Agarwalf9607272012-06-13 05:32:43 +05302922 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002923 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2924 MGMT_STATUS_NOT_CONNECTED, &rp,
2925 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002926 goto failed;
2927 }
2928
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002929 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002930 if (!cmd) {
2931 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002932 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002933 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002934
Johan Hedbergf5818c22014-12-05 13:36:02 +02002935 cmd->cmd_complete = generic_cmd_complete;
2936
Johan Hedberge3f2f922014-08-18 20:33:33 +03002937 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002938 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002939 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002940
2941failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002942 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002943 return err;
2944}
2945
Andre Guedes57c14772012-04-24 21:02:50 -03002946static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002947{
2948 switch (link_type) {
2949 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002950 switch (addr_type) {
2951 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002952 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002953
Johan Hedberg48264f02011-11-09 13:58:58 +02002954 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002955 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002956 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002957 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002958
Johan Hedberg4c659c32011-11-07 23:13:39 +02002959 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002960 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002961 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002962 }
2963}
2964
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002965static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2966 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002967{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002968 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002969 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002970 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002971 int err;
2972 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002973
2974 BT_DBG("");
2975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002976 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002977
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002978 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002979 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2980 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002981 goto unlock;
2982 }
2983
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002984 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002985 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2986 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002987 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002988 }
2989
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002990 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002991 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002992 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002993 err = -ENOMEM;
2994 goto unlock;
2995 }
2996
Johan Hedberg2784eb42011-01-21 13:56:35 +02002997 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002998 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002999 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3000 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003001 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003002 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003003 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003004 continue;
3005 i++;
3006 }
3007
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003008 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003009
Johan Hedberg4c659c32011-11-07 23:13:39 +02003010 /* Recalculate length in case of filtered SCO connections, etc */
3011 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003012
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003013 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3014 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003015
Johan Hedberga38528f2011-01-22 06:46:43 +02003016 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003017
3018unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003019 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003020 return err;
3021}
3022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003023static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003024 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003025{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003026 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003027 int err;
3028
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003029 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003030 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003031 if (!cmd)
3032 return -ENOMEM;
3033
Johan Hedbergd8457692012-02-17 14:24:57 +02003034 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003035 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003036 if (err < 0)
3037 mgmt_pending_remove(cmd);
3038
3039 return err;
3040}
3041
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003042static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003043 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003044{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003045 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003046 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003047 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003048 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003049 int err;
3050
3051 BT_DBG("");
3052
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003053 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003054
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003055 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003056 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3057 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003058 goto failed;
3059 }
3060
Johan Hedbergd8457692012-02-17 14:24:57 +02003061 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003062 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003063 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3064 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003065 goto failed;
3066 }
3067
3068 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003069 struct mgmt_cp_pin_code_neg_reply ncp;
3070
3071 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003072
3073 BT_ERR("PIN code is not 16 bytes long");
3074
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003075 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003076 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003077 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3078 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003079
3080 goto failed;
3081 }
3082
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003083 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003084 if (!cmd) {
3085 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003086 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003087 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003088
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003089 cmd->cmd_complete = addr_cmd_complete;
3090
Johan Hedbergd8457692012-02-17 14:24:57 +02003091 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003092 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003093 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003094
3095 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3096 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003097 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003098
3099failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003100 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003101 return err;
3102}
3103
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003104static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3105 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003106{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003107 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003108
3109 BT_DBG("");
3110
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003111 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003112 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3113 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003114
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003115 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003116
3117 hdev->io_capability = cp->io_capability;
3118
3119 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003120 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003121
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003122 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003123
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003124 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3125 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003126}
3127
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003128static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003129{
3130 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003131 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003132
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003133 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003134 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3135 continue;
3136
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137 if (cmd->user_data != conn)
3138 continue;
3139
3140 return cmd;
3141 }
3142
3143 return NULL;
3144}
3145
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003146static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003147{
3148 struct mgmt_rp_pair_device rp;
3149 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003150 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003151
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003152 bacpy(&rp.addr.bdaddr, &conn->dst);
3153 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003154
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003155 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3156 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003157
3158 /* So we don't get further callbacks for this connection */
3159 conn->connect_cfm_cb = NULL;
3160 conn->security_cfm_cb = NULL;
3161 conn->disconn_cfm_cb = NULL;
3162
David Herrmann76a68ba2013-04-06 20:28:37 +02003163 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003164
3165 /* The device is paired so there is no need to remove
3166 * its connection parameters anymore.
3167 */
3168 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003169
3170 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003171
3172 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003173}
3174
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003175void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3176{
3177 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003178 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003179
3180 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003181 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003182 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003183 mgmt_pending_remove(cmd);
3184 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003185}
3186
Johan Hedberge9a416b2011-02-19 12:05:56 -03003187static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3188{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003189 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003190
3191 BT_DBG("status %u", status);
3192
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003193 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003194 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003195 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003196 return;
3197 }
3198
3199 cmd->cmd_complete(cmd, mgmt_status(status));
3200 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003201}
3202
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003203static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303204{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003205 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303206
3207 BT_DBG("status %u", status);
3208
3209 if (!status)
3210 return;
3211
3212 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003213 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303214 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003215 return;
3216 }
3217
3218 cmd->cmd_complete(cmd, mgmt_status(status));
3219 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303220}
3221
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003222static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003223 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003224{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003225 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003226 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003227 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003228 u8 sec_level, auth_type;
3229 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003230 int err;
3231
3232 BT_DBG("");
3233
Szymon Jancf950a30e2013-01-18 12:48:07 +01003234 memset(&rp, 0, sizeof(rp));
3235 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3236 rp.addr.type = cp->addr.type;
3237
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003238 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003239 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3240 MGMT_STATUS_INVALID_PARAMS,
3241 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003242
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003243 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003244 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3245 MGMT_STATUS_INVALID_PARAMS,
3246 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003247
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003248 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003249
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003250 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003251 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3252 MGMT_STATUS_NOT_POWERED, &rp,
3253 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003254 goto unlock;
3255 }
3256
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003257 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003258 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003259
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003260 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003261 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3262 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003263 } else {
3264 u8 addr_type;
3265
3266 /* Convert from L2CAP channel address type to HCI address type
3267 */
3268 if (cp->addr.type == BDADDR_LE_PUBLIC)
3269 addr_type = ADDR_LE_DEV_PUBLIC;
3270 else
3271 addr_type = ADDR_LE_DEV_RANDOM;
3272
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003273 /* When pairing a new device, it is expected to remember
3274 * this device for future connections. Adding the connection
3275 * parameter information ahead of time allows tracking
3276 * of the slave preferred values and will speed up any
3277 * further connection establishment.
3278 *
3279 * If connection parameters already exist, then they
3280 * will be kept and this function does nothing.
3281 */
3282 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3283
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003284 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003285 sec_level, HCI_LE_CONN_TIMEOUT,
3286 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003287 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003288
Ville Tervo30e76272011-02-22 16:10:53 -03003289 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003290 int status;
3291
3292 if (PTR_ERR(conn) == -EBUSY)
3293 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003294 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3295 status = MGMT_STATUS_NOT_SUPPORTED;
3296 else if (PTR_ERR(conn) == -ECONNREFUSED)
3297 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003298 else
3299 status = MGMT_STATUS_CONNECT_FAILED;
3300
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003301 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3302 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003303 goto unlock;
3304 }
3305
3306 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003307 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003308 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3309 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003310 goto unlock;
3311 }
3312
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003313 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003314 if (!cmd) {
3315 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003316 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003317 goto unlock;
3318 }
3319
Johan Hedberg04ab2742014-12-05 13:36:04 +02003320 cmd->cmd_complete = pairing_complete;
3321
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003322 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003323 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003324 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003325 conn->security_cfm_cb = pairing_complete_cb;
3326 conn->disconn_cfm_cb = pairing_complete_cb;
3327 } else {
3328 conn->connect_cfm_cb = le_pairing_complete_cb;
3329 conn->security_cfm_cb = le_pairing_complete_cb;
3330 conn->disconn_cfm_cb = le_pairing_complete_cb;
3331 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003332
Johan Hedberge9a416b2011-02-19 12:05:56 -03003333 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003334 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003335
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003336 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003337 hci_conn_security(conn, sec_level, auth_type, true)) {
3338 cmd->cmd_complete(cmd, 0);
3339 mgmt_pending_remove(cmd);
3340 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003341
3342 err = 0;
3343
3344unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003345 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003346 return err;
3347}
3348
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003349static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3350 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003351{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003352 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003353 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003354 struct hci_conn *conn;
3355 int err;
3356
3357 BT_DBG("");
3358
Johan Hedberg28424702012-02-02 04:02:29 +02003359 hci_dev_lock(hdev);
3360
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003361 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003362 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3363 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003364 goto unlock;
3365 }
3366
Johan Hedberg28424702012-02-02 04:02:29 +02003367 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3368 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003369 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3370 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003371 goto unlock;
3372 }
3373
3374 conn = cmd->user_data;
3375
3376 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003377 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3378 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003379 goto unlock;
3380 }
3381
Johan Hedberga511b352014-12-11 21:45:45 +02003382 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3383 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003385 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3386 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003387unlock:
3388 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003389 return err;
3390}
3391
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003392static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003393 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003394 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003395{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003396 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003397 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003398 int err;
3399
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003400 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003401
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003402 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003403 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3404 MGMT_STATUS_NOT_POWERED, addr,
3405 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003406 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003407 }
3408
Johan Hedberg1707c602013-03-15 17:07:15 -05003409 if (addr->type == BDADDR_BREDR)
3410 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003411 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003412 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003413
Johan Hedberg272d90d2012-02-09 15:26:12 +02003414 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003415 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3416 MGMT_STATUS_NOT_CONNECTED, addr,
3417 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003418 goto done;
3419 }
3420
Johan Hedberg1707c602013-03-15 17:07:15 -05003421 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003422 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003423 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003424 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3425 MGMT_STATUS_SUCCESS, addr,
3426 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003427 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003428 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3429 MGMT_STATUS_FAILED, addr,
3430 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003431
Brian Gix47c15e22011-11-16 13:53:14 -08003432 goto done;
3433 }
3434
Johan Hedberg1707c602013-03-15 17:07:15 -05003435 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003436 if (!cmd) {
3437 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003438 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003439 }
3440
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003441 cmd->cmd_complete = addr_cmd_complete;
3442
Brian Gix0df4c182011-11-16 13:53:13 -08003443 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003444 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3445 struct hci_cp_user_passkey_reply cp;
3446
Johan Hedberg1707c602013-03-15 17:07:15 -05003447 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003448 cp.passkey = passkey;
3449 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3450 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003451 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3452 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003453
Johan Hedberga664b5b2011-02-19 12:06:02 -03003454 if (err < 0)
3455 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003456
Brian Gix0df4c182011-11-16 13:53:13 -08003457done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003458 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003459 return err;
3460}
3461
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303462static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3463 void *data, u16 len)
3464{
3465 struct mgmt_cp_pin_code_neg_reply *cp = data;
3466
3467 BT_DBG("");
3468
Johan Hedberg1707c602013-03-15 17:07:15 -05003469 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303470 MGMT_OP_PIN_CODE_NEG_REPLY,
3471 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3472}
3473
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003474static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3475 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003477 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003478
3479 BT_DBG("");
3480
3481 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003482 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3483 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003484
Johan Hedberg1707c602013-03-15 17:07:15 -05003485 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003486 MGMT_OP_USER_CONFIRM_REPLY,
3487 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003488}
3489
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003490static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003491 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003492{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003493 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003494
3495 BT_DBG("");
3496
Johan Hedberg1707c602013-03-15 17:07:15 -05003497 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003498 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3499 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003500}
3501
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3503 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003504{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003505 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003506
3507 BT_DBG("");
3508
Johan Hedberg1707c602013-03-15 17:07:15 -05003509 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003510 MGMT_OP_USER_PASSKEY_REPLY,
3511 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003512}
3513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003515 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003516{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003517 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003518
3519 BT_DBG("");
3520
Johan Hedberg1707c602013-03-15 17:07:15 -05003521 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003522 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3523 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003524}
3525
Johan Hedberg13928972013-03-15 17:07:00 -05003526static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003527{
Johan Hedberg13928972013-03-15 17:07:00 -05003528 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003529 struct hci_cp_write_local_name cp;
3530
Johan Hedberg13928972013-03-15 17:07:00 -05003531 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003532
Johan Hedberg890ea892013-03-15 17:06:52 -05003533 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003534}
3535
Marcel Holtmann1904a852015-01-11 13:50:44 -08003536static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003537{
3538 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003539 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003540
3541 BT_DBG("status 0x%02x", status);
3542
3543 hci_dev_lock(hdev);
3544
3545 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3546 if (!cmd)
3547 goto unlock;
3548
3549 cp = cmd->param;
3550
3551 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003552 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3553 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003554 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003555 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3556 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003557
3558 mgmt_pending_remove(cmd);
3559
3560unlock:
3561 hci_dev_unlock(hdev);
3562}
3563
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003564static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003565 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003566{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003567 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003568 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003569 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003570 int err;
3571
3572 BT_DBG("");
3573
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003574 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003575
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003576 /* If the old values are the same as the new ones just return a
3577 * direct command complete event.
3578 */
3579 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3580 !memcmp(hdev->short_name, cp->short_name,
3581 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003582 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3583 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003584 goto failed;
3585 }
3586
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003587 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003588
Johan Hedbergb5235a62012-02-21 14:32:24 +02003589 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003590 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003591
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003592 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3593 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003594 if (err < 0)
3595 goto failed;
3596
3597 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003598 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003599
Johan Hedbergb5235a62012-02-21 14:32:24 +02003600 goto failed;
3601 }
3602
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003603 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003604 if (!cmd) {
3605 err = -ENOMEM;
3606 goto failed;
3607 }
3608
Johan Hedberg13928972013-03-15 17:07:00 -05003609 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3610
Johan Hedberg890ea892013-03-15 17:06:52 -05003611 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003612
3613 if (lmp_bredr_capable(hdev)) {
3614 update_name(&req);
3615 update_eir(&req);
3616 }
3617
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003618 /* The name is stored in the scan response data and so
3619 * no need to udpate the advertising data here.
3620 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003621 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003622 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003623
Johan Hedberg13928972013-03-15 17:07:00 -05003624 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003625 if (err < 0)
3626 mgmt_pending_remove(cmd);
3627
3628failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003629 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003630 return err;
3631}
3632
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003633static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003634 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003635{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003636 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003637 int err;
3638
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003639 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003640
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003641 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003642
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003643 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003644 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3645 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003646 goto unlock;
3647 }
3648
Andre Guedes9a1a1992012-07-24 15:03:48 -03003649 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003650 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3651 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003652 goto unlock;
3653 }
3654
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003655 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003656 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3657 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003658 goto unlock;
3659 }
3660
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003661 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003662 if (!cmd) {
3663 err = -ENOMEM;
3664 goto unlock;
3665 }
3666
Johan Hedberg710f11c2014-05-26 11:21:22 +03003667 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003668 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3669 0, NULL);
3670 else
3671 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3672
Szymon Jancc35938b2011-03-22 13:12:21 +01003673 if (err < 0)
3674 mgmt_pending_remove(cmd);
3675
3676unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003677 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003678 return err;
3679}
3680
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003681static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003682 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003683{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003684 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003685 int err;
3686
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003687 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003688
Johan Hedberg5d57e792015-01-23 10:10:38 +02003689 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003690 return mgmt_cmd_complete(sk, hdev->id,
3691 MGMT_OP_ADD_REMOTE_OOB_DATA,
3692 MGMT_STATUS_INVALID_PARAMS,
3693 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003694
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003695 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003696
Marcel Holtmannec109112014-01-10 02:07:30 -08003697 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3698 struct mgmt_cp_add_remote_oob_data *cp = data;
3699 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003700
Johan Hedbergc19a4952014-11-17 20:52:19 +02003701 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003702 err = mgmt_cmd_complete(sk, hdev->id,
3703 MGMT_OP_ADD_REMOTE_OOB_DATA,
3704 MGMT_STATUS_INVALID_PARAMS,
3705 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003706 goto unlock;
3707 }
3708
Marcel Holtmannec109112014-01-10 02:07:30 -08003709 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003710 cp->addr.type, cp->hash,
3711 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003712 if (err < 0)
3713 status = MGMT_STATUS_FAILED;
3714 else
3715 status = MGMT_STATUS_SUCCESS;
3716
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003717 err = mgmt_cmd_complete(sk, hdev->id,
3718 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3719 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003720 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3721 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003722 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003723 u8 status;
3724
Johan Hedberg86df9202014-10-26 20:52:27 +01003725 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003726 /* Enforce zero-valued 192-bit parameters as
3727 * long as legacy SMP OOB isn't implemented.
3728 */
3729 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3730 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003731 err = mgmt_cmd_complete(sk, hdev->id,
3732 MGMT_OP_ADD_REMOTE_OOB_DATA,
3733 MGMT_STATUS_INVALID_PARAMS,
3734 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003735 goto unlock;
3736 }
3737
Johan Hedberg86df9202014-10-26 20:52:27 +01003738 rand192 = NULL;
3739 hash192 = NULL;
3740 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003741 /* In case one of the P-192 values is set to zero,
3742 * then just disable OOB data for P-192.
3743 */
3744 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3745 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3746 rand192 = NULL;
3747 hash192 = NULL;
3748 } else {
3749 rand192 = cp->rand192;
3750 hash192 = cp->hash192;
3751 }
3752 }
3753
3754 /* In case one of the P-256 values is set to zero, then just
3755 * disable OOB data for P-256.
3756 */
3757 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3758 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3759 rand256 = NULL;
3760 hash256 = NULL;
3761 } else {
3762 rand256 = cp->rand256;
3763 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003764 }
3765
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003766 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003767 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003768 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003769 if (err < 0)
3770 status = MGMT_STATUS_FAILED;
3771 else
3772 status = MGMT_STATUS_SUCCESS;
3773
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003774 err = mgmt_cmd_complete(sk, hdev->id,
3775 MGMT_OP_ADD_REMOTE_OOB_DATA,
3776 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003777 } else {
3778 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003779 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3780 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003781 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003782
Johan Hedbergc19a4952014-11-17 20:52:19 +02003783unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003784 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003785 return err;
3786}
3787
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003788static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003789 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003790{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003791 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003792 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003793 int err;
3794
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003795 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003796
Johan Hedbergc19a4952014-11-17 20:52:19 +02003797 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003798 return mgmt_cmd_complete(sk, hdev->id,
3799 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3800 MGMT_STATUS_INVALID_PARAMS,
3801 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003802
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003803 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003804
Johan Hedbergeedbd582014-11-15 09:34:23 +02003805 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3806 hci_remote_oob_data_clear(hdev);
3807 status = MGMT_STATUS_SUCCESS;
3808 goto done;
3809 }
3810
Johan Hedberg6928a922014-10-26 20:46:09 +01003811 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003812 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003813 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003814 else
Szymon Janca6785be2012-12-13 15:11:21 +01003815 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003816
Johan Hedbergeedbd582014-11-15 09:34:23 +02003817done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003818 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3819 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003820
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003821 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003822 return err;
3823}
3824
Marcel Holtmann80190442014-12-04 11:36:36 +01003825static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003826{
Marcel Holtmann80190442014-12-04 11:36:36 +01003827 struct hci_dev *hdev = req->hdev;
3828 struct hci_cp_le_set_scan_param param_cp;
3829 struct hci_cp_le_set_scan_enable enable_cp;
3830 struct hci_cp_inquiry inq_cp;
3831 /* General inquiry access code (GIAC) */
3832 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3833 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003834 int err;
3835
Marcel Holtmann80190442014-12-04 11:36:36 +01003836 switch (hdev->discovery.type) {
3837 case DISCOV_TYPE_BREDR:
3838 *status = mgmt_bredr_support(hdev);
3839 if (*status)
3840 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003841
Marcel Holtmann80190442014-12-04 11:36:36 +01003842 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3843 *status = MGMT_STATUS_BUSY;
3844 return false;
3845 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003846
Marcel Holtmann80190442014-12-04 11:36:36 +01003847 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003848
Marcel Holtmann80190442014-12-04 11:36:36 +01003849 memset(&inq_cp, 0, sizeof(inq_cp));
3850 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3851 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3852 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3853 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003854
Marcel Holtmann80190442014-12-04 11:36:36 +01003855 case DISCOV_TYPE_LE:
3856 case DISCOV_TYPE_INTERLEAVED:
3857 *status = mgmt_le_support(hdev);
3858 if (*status)
3859 return false;
3860
3861 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3862 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3863 *status = MGMT_STATUS_NOT_SUPPORTED;
3864 return false;
3865 }
3866
3867 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3868 /* Don't let discovery abort an outgoing
3869 * connection attempt that's using directed
3870 * advertising.
3871 */
3872 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3873 BT_CONNECT)) {
3874 *status = MGMT_STATUS_REJECTED;
3875 return false;
3876 }
3877
3878 disable_advertising(req);
3879 }
3880
3881 /* If controller is scanning, it means the background scanning
3882 * is running. Thus, we should temporarily stop it in order to
3883 * set the discovery scanning parameters.
3884 */
3885 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3886 hci_req_add_le_scan_disable(req);
3887
3888 memset(&param_cp, 0, sizeof(param_cp));
3889
3890 /* All active scans will be done with either a resolvable
3891 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003892 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003893 */
3894 err = hci_update_random_address(req, true, &own_addr_type);
3895 if (err < 0) {
3896 *status = MGMT_STATUS_FAILED;
3897 return false;
3898 }
3899
3900 param_cp.type = LE_SCAN_ACTIVE;
3901 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3902 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3903 param_cp.own_address_type = own_addr_type;
3904 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3905 &param_cp);
3906
3907 memset(&enable_cp, 0, sizeof(enable_cp));
3908 enable_cp.enable = LE_SCAN_ENABLE;
3909 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3910 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3911 &enable_cp);
3912 break;
3913
3914 default:
3915 *status = MGMT_STATUS_INVALID_PARAMS;
3916 return false;
3917 }
3918
3919 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003920}
3921
Marcel Holtmann1904a852015-01-11 13:50:44 -08003922static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3923 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003924{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003925 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003926 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003927
Andre Guedes7c307722013-04-30 15:29:28 -03003928 BT_DBG("status %d", status);
3929
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003930 hci_dev_lock(hdev);
3931
3932 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003933 if (!cmd)
3934 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3935
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003936 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003937 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003938 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003939 }
3940
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003941 if (status) {
3942 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3943 goto unlock;
3944 }
3945
Andre Guedes7c307722013-04-30 15:29:28 -03003946 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003947
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003948 /* If the scan involves LE scan, pick proper timeout to schedule
3949 * hdev->le_scan_disable that will stop it.
3950 */
Andre Guedes7c307722013-04-30 15:29:28 -03003951 switch (hdev->discovery.type) {
3952 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003953 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003954 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003955 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003956 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003957 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003958 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003959 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003960 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003961 default:
3962 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003963 timeout = 0;
3964 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003965 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003966
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003967 if (timeout) {
3968 /* When service discovery is used and the controller has
3969 * a strict duplicate filter, it is important to remember
3970 * the start and duration of the scan. This is required
3971 * for restarting scanning during the discovery phase.
3972 */
3973 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3974 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003975 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003976 hdev->discovery.scan_start = jiffies;
3977 hdev->discovery.scan_duration = timeout;
3978 }
3979
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003980 queue_delayed_work(hdev->workqueue,
3981 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003982 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003983
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003984unlock:
3985 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003986}
3987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003988static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003989 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003990{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003991 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003992 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003993 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003994 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003995 int err;
3996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003997 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003998
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003999 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004000
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004001 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004002 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4003 MGMT_STATUS_NOT_POWERED,
4004 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004005 goto failed;
4006 }
4007
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004008 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4009 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004010 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4011 MGMT_STATUS_BUSY, &cp->type,
4012 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004013 goto failed;
4014 }
4015
Johan Hedberg2922a942014-12-05 13:36:06 +02004016 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004017 if (!cmd) {
4018 err = -ENOMEM;
4019 goto failed;
4020 }
4021
Johan Hedberg2922a942014-12-05 13:36:06 +02004022 cmd->cmd_complete = generic_cmd_complete;
4023
Marcel Holtmann22078802014-12-05 11:45:22 +01004024 /* Clear the discovery filter first to free any previously
4025 * allocated memory for the UUID list.
4026 */
4027 hci_discovery_filter_clear(hdev);
4028
Andre Guedes4aab14e2012-02-17 20:39:36 -03004029 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004030 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004031
Andre Guedes7c307722013-04-30 15:29:28 -03004032 hci_req_init(&req, hdev);
4033
Marcel Holtmann80190442014-12-04 11:36:36 +01004034 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004035 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4036 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004037 mgmt_pending_remove(cmd);
4038 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004039 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004040
Andre Guedes7c307722013-04-30 15:29:28 -03004041 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004042 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004043 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004044 goto failed;
4045 }
4046
4047 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004048
4049failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004050 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004051 return err;
4052}
4053
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004054static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4055 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004056{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004057 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4058 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004059}
4060
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004061static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4062 void *data, u16 len)
4063{
4064 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004065 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004066 struct hci_request req;
4067 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4068 u16 uuid_count, expected_len;
4069 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004070 int err;
4071
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004072 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004073
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004074 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004075
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004076 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004077 err = mgmt_cmd_complete(sk, hdev->id,
4078 MGMT_OP_START_SERVICE_DISCOVERY,
4079 MGMT_STATUS_NOT_POWERED,
4080 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004081 goto failed;
4082 }
4083
4084 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4085 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004086 err = mgmt_cmd_complete(sk, hdev->id,
4087 MGMT_OP_START_SERVICE_DISCOVERY,
4088 MGMT_STATUS_BUSY, &cp->type,
4089 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004090 goto failed;
4091 }
4092
4093 uuid_count = __le16_to_cpu(cp->uuid_count);
4094 if (uuid_count > max_uuid_count) {
4095 BT_ERR("service_discovery: too big uuid_count value %u",
4096 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004097 err = mgmt_cmd_complete(sk, hdev->id,
4098 MGMT_OP_START_SERVICE_DISCOVERY,
4099 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4100 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004101 goto failed;
4102 }
4103
4104 expected_len = sizeof(*cp) + uuid_count * 16;
4105 if (expected_len != len) {
4106 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4107 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004108 err = mgmt_cmd_complete(sk, hdev->id,
4109 MGMT_OP_START_SERVICE_DISCOVERY,
4110 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4111 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004112 goto failed;
4113 }
4114
4115 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004116 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004117 if (!cmd) {
4118 err = -ENOMEM;
4119 goto failed;
4120 }
4121
Johan Hedberg2922a942014-12-05 13:36:06 +02004122 cmd->cmd_complete = service_discovery_cmd_complete;
4123
Marcel Holtmann22078802014-12-05 11:45:22 +01004124 /* Clear the discovery filter first to free any previously
4125 * allocated memory for the UUID list.
4126 */
4127 hci_discovery_filter_clear(hdev);
4128
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004129 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004130 hdev->discovery.type = cp->type;
4131 hdev->discovery.rssi = cp->rssi;
4132 hdev->discovery.uuid_count = uuid_count;
4133
4134 if (uuid_count > 0) {
4135 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4136 GFP_KERNEL);
4137 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004138 err = mgmt_cmd_complete(sk, hdev->id,
4139 MGMT_OP_START_SERVICE_DISCOVERY,
4140 MGMT_STATUS_FAILED,
4141 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004142 mgmt_pending_remove(cmd);
4143 goto failed;
4144 }
4145 }
4146
4147 hci_req_init(&req, hdev);
4148
4149 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004150 err = mgmt_cmd_complete(sk, hdev->id,
4151 MGMT_OP_START_SERVICE_DISCOVERY,
4152 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004153 mgmt_pending_remove(cmd);
4154 goto failed;
4155 }
4156
4157 err = hci_req_run(&req, start_discovery_complete);
4158 if (err < 0) {
4159 mgmt_pending_remove(cmd);
4160 goto failed;
4161 }
4162
4163 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4164
4165failed:
4166 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004167 return err;
4168}
4169
Marcel Holtmann1904a852015-01-11 13:50:44 -08004170static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004171{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004172 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004173
Andre Guedes0e05bba2013-04-30 15:29:33 -03004174 BT_DBG("status %d", status);
4175
4176 hci_dev_lock(hdev);
4177
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004178 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4179 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004180 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004181 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004182 }
4183
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004184 if (!status)
4185 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004186
Andre Guedes0e05bba2013-04-30 15:29:33 -03004187 hci_dev_unlock(hdev);
4188}
4189
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004190static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004191 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004192{
Johan Hedbergd9306502012-02-20 23:25:18 +02004193 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004194 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004195 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004196 int err;
4197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004198 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004199
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004200 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004201
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004202 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004203 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4204 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4205 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004206 goto unlock;
4207 }
4208
4209 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004210 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4211 MGMT_STATUS_INVALID_PARAMS,
4212 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004213 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004214 }
4215
Johan Hedberg2922a942014-12-05 13:36:06 +02004216 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004217 if (!cmd) {
4218 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004219 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004220 }
4221
Johan Hedberg2922a942014-12-05 13:36:06 +02004222 cmd->cmd_complete = generic_cmd_complete;
4223
Andre Guedes0e05bba2013-04-30 15:29:33 -03004224 hci_req_init(&req, hdev);
4225
Johan Hedberg21a60d32014-06-10 14:05:58 +03004226 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004227
Johan Hedberg21a60d32014-06-10 14:05:58 +03004228 err = hci_req_run(&req, stop_discovery_complete);
4229 if (!err) {
4230 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004231 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004232 }
4233
Johan Hedberg21a60d32014-06-10 14:05:58 +03004234 mgmt_pending_remove(cmd);
4235
4236 /* If no HCI commands were sent we're done */
4237 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004238 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4239 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004240 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4241 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004242
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004243unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004244 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004245 return err;
4246}
4247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004248static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004249 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004250{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004251 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004252 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004253 int err;
4254
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004255 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004256
Johan Hedberg561aafb2012-01-04 13:31:59 +02004257 hci_dev_lock(hdev);
4258
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004259 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004260 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4261 MGMT_STATUS_FAILED, &cp->addr,
4262 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004263 goto failed;
4264 }
4265
Johan Hedberga198e7b2012-02-17 14:27:06 +02004266 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004267 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004268 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4269 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4270 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004271 goto failed;
4272 }
4273
4274 if (cp->name_known) {
4275 e->name_state = NAME_KNOWN;
4276 list_del(&e->list);
4277 } else {
4278 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004279 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004280 }
4281
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004282 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4283 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004284
4285failed:
4286 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004287 return err;
4288}
4289
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004290static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004291 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004292{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004293 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004294 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004295 int err;
4296
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004297 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004298
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004299 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004300 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4301 MGMT_STATUS_INVALID_PARAMS,
4302 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004303
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004304 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004305
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004306 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4307 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004308 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004309 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004310 goto done;
4311 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004312
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004313 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4314 sk);
4315 status = MGMT_STATUS_SUCCESS;
4316
4317done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004318 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4319 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004320
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004321 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004322
4323 return err;
4324}
4325
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004326static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004327 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004328{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004329 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004330 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004331 int err;
4332
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004333 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004334
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004335 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004336 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4337 MGMT_STATUS_INVALID_PARAMS,
4338 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004339
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004340 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004341
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004342 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4343 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004344 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004345 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004346 goto done;
4347 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004348
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004349 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4350 sk);
4351 status = MGMT_STATUS_SUCCESS;
4352
4353done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004354 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4355 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004356
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004357 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004358
4359 return err;
4360}
4361
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004362static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4363 u16 len)
4364{
4365 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004366 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004367 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004368 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004369
4370 BT_DBG("%s", hdev->name);
4371
Szymon Jancc72d4b82012-03-16 16:02:57 +01004372 source = __le16_to_cpu(cp->source);
4373
4374 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004375 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4376 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004377
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004378 hci_dev_lock(hdev);
4379
Szymon Jancc72d4b82012-03-16 16:02:57 +01004380 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004381 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4382 hdev->devid_product = __le16_to_cpu(cp->product);
4383 hdev->devid_version = __le16_to_cpu(cp->version);
4384
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004385 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4386 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004387
Johan Hedberg890ea892013-03-15 17:06:52 -05004388 hci_req_init(&req, hdev);
4389 update_eir(&req);
4390 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004391
4392 hci_dev_unlock(hdev);
4393
4394 return err;
4395}
4396
Marcel Holtmann1904a852015-01-11 13:50:44 -08004397static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4398 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004399{
4400 struct cmd_lookup match = { NULL, hdev };
4401
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304402 hci_dev_lock(hdev);
4403
Johan Hedberg4375f102013-09-25 13:26:10 +03004404 if (status) {
4405 u8 mgmt_err = mgmt_status(status);
4406
4407 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4408 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304409 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004410 }
4411
Johan Hedbergc93bd152014-07-08 15:07:48 +03004412 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4413 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4414 else
4415 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4416
Johan Hedberg4375f102013-09-25 13:26:10 +03004417 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4418 &match);
4419
4420 new_settings(hdev, match.sk);
4421
4422 if (match.sk)
4423 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304424
4425unlock:
4426 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004427}
4428
Marcel Holtmann21b51872013-10-10 09:47:53 -07004429static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4430 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004431{
4432 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004433 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004434 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004435 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004436 int err;
4437
4438 BT_DBG("request for %s", hdev->name);
4439
Johan Hedberge6fe7982013-10-02 15:45:22 +03004440 status = mgmt_le_support(hdev);
4441 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004442 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4443 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004444
4445 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004446 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4447 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004448
4449 hci_dev_lock(hdev);
4450
4451 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004452 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004453
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004454 /* The following conditions are ones which mean that we should
4455 * not do any HCI communication but directly send a mgmt
4456 * response to user space (after toggling the flag if
4457 * necessary).
4458 */
4459 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004460 hci_conn_num(hdev, LE_LINK) > 0 ||
4461 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4462 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004463 bool changed = false;
4464
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004465 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4466 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004467 changed = true;
4468 }
4469
4470 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4471 if (err < 0)
4472 goto unlock;
4473
4474 if (changed)
4475 err = new_settings(hdev, sk);
4476
4477 goto unlock;
4478 }
4479
4480 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4481 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004482 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4483 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004484 goto unlock;
4485 }
4486
4487 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4488 if (!cmd) {
4489 err = -ENOMEM;
4490 goto unlock;
4491 }
4492
4493 hci_req_init(&req, hdev);
4494
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004495 if (val)
4496 enable_advertising(&req);
4497 else
4498 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004499
4500 err = hci_req_run(&req, set_advertising_complete);
4501 if (err < 0)
4502 mgmt_pending_remove(cmd);
4503
4504unlock:
4505 hci_dev_unlock(hdev);
4506 return err;
4507}
4508
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004509static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4510 void *data, u16 len)
4511{
4512 struct mgmt_cp_set_static_address *cp = data;
4513 int err;
4514
4515 BT_DBG("%s", hdev->name);
4516
Marcel Holtmann62af4442013-10-02 22:10:32 -07004517 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004518 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4519 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004520
4521 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004522 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4523 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004524
4525 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4526 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004527 return mgmt_cmd_status(sk, hdev->id,
4528 MGMT_OP_SET_STATIC_ADDRESS,
4529 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004530
4531 /* Two most significant bits shall be set */
4532 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004533 return mgmt_cmd_status(sk, hdev->id,
4534 MGMT_OP_SET_STATIC_ADDRESS,
4535 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004536 }
4537
4538 hci_dev_lock(hdev);
4539
4540 bacpy(&hdev->static_addr, &cp->bdaddr);
4541
Marcel Holtmann93690c22015-03-06 10:11:21 -08004542 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4543 if (err < 0)
4544 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004545
Marcel Holtmann93690c22015-03-06 10:11:21 -08004546 err = new_settings(hdev, sk);
4547
4548unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004549 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004550 return err;
4551}
4552
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004553static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4554 void *data, u16 len)
4555{
4556 struct mgmt_cp_set_scan_params *cp = data;
4557 __u16 interval, window;
4558 int err;
4559
4560 BT_DBG("%s", hdev->name);
4561
4562 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004563 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4564 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004565
4566 interval = __le16_to_cpu(cp->interval);
4567
4568 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004569 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4570 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004571
4572 window = __le16_to_cpu(cp->window);
4573
4574 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004575 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4576 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004577
Marcel Holtmann899e1072013-10-14 09:55:32 -07004578 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004579 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4580 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004581
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004582 hci_dev_lock(hdev);
4583
4584 hdev->le_scan_interval = interval;
4585 hdev->le_scan_window = window;
4586
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004587 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4588 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004589
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004590 /* If background scan is running, restart it so new parameters are
4591 * loaded.
4592 */
4593 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4594 hdev->discovery.state == DISCOVERY_STOPPED) {
4595 struct hci_request req;
4596
4597 hci_req_init(&req, hdev);
4598
4599 hci_req_add_le_scan_disable(&req);
4600 hci_req_add_le_passive_scan(&req);
4601
4602 hci_req_run(&req, NULL);
4603 }
4604
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004605 hci_dev_unlock(hdev);
4606
4607 return err;
4608}
4609
Marcel Holtmann1904a852015-01-11 13:50:44 -08004610static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4611 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004612{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004613 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004614
4615 BT_DBG("status 0x%02x", status);
4616
4617 hci_dev_lock(hdev);
4618
4619 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4620 if (!cmd)
4621 goto unlock;
4622
4623 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004624 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4625 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004626 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004627 struct mgmt_mode *cp = cmd->param;
4628
4629 if (cp->val)
4630 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4631 else
4632 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4633
Johan Hedberg33e38b32013-03-15 17:07:05 -05004634 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4635 new_settings(hdev, cmd->sk);
4636 }
4637
4638 mgmt_pending_remove(cmd);
4639
4640unlock:
4641 hci_dev_unlock(hdev);
4642}
4643
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004644static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004645 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004646{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004647 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004648 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004649 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004650 int err;
4651
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004652 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004653
Johan Hedberg56f87902013-10-02 13:43:13 +03004654 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4655 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004656 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4657 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004658
Johan Hedberga7e80f22013-01-09 16:05:19 +02004659 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004660 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4661 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004662
Johan Hedberg5400c042012-02-21 16:40:33 +02004663 if (!hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004664 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4665 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004666
4667 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004668 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4669 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004670
4671 hci_dev_lock(hdev);
4672
Johan Hedberg05cbf292013-03-15 17:07:07 -05004673 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004674 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4675 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004676 goto unlock;
4677 }
4678
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004679 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4680 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4681 hdev);
4682 goto unlock;
4683 }
4684
Johan Hedberg33e38b32013-03-15 17:07:05 -05004685 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4686 data, len);
4687 if (!cmd) {
4688 err = -ENOMEM;
4689 goto unlock;
4690 }
4691
4692 hci_req_init(&req, hdev);
4693
Johan Hedberg406d7802013-03-15 17:07:09 -05004694 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004695
4696 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004697 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004698 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4699 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004700 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004701 }
4702
Johan Hedberg33e38b32013-03-15 17:07:05 -05004703unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004704 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004705
Antti Julkuf6422ec2011-06-22 13:11:56 +03004706 return err;
4707}
4708
Marcel Holtmann1904a852015-01-11 13:50:44 -08004709static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004710{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004711 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004712
4713 BT_DBG("status 0x%02x", status);
4714
4715 hci_dev_lock(hdev);
4716
4717 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4718 if (!cmd)
4719 goto unlock;
4720
4721 if (status) {
4722 u8 mgmt_err = mgmt_status(status);
4723
4724 /* We need to restore the flag if related HCI commands
4725 * failed.
4726 */
4727 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4728
Johan Hedberga69e8372015-03-06 21:08:53 +02004729 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004730 } else {
4731 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4732 new_settings(hdev, cmd->sk);
4733 }
4734
4735 mgmt_pending_remove(cmd);
4736
4737unlock:
4738 hci_dev_unlock(hdev);
4739}
4740
4741static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4742{
4743 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004744 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004745 struct hci_request req;
4746 int err;
4747
4748 BT_DBG("request for %s", hdev->name);
4749
4750 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004751 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4752 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004753
4754 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004755 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4756 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004757
4758 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004759 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4760 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004761
4762 hci_dev_lock(hdev);
4763
4764 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4765 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4766 goto unlock;
4767 }
4768
4769 if (!hdev_is_powered(hdev)) {
4770 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004771 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4772 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4773 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4774 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4775 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4776 }
4777
4778 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4779
4780 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4781 if (err < 0)
4782 goto unlock;
4783
4784 err = new_settings(hdev, sk);
4785 goto unlock;
4786 }
4787
4788 /* Reject disabling when powered on */
4789 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004790 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4791 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004792 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004793 } else {
4794 /* When configuring a dual-mode controller to operate
4795 * with LE only and using a static address, then switching
4796 * BR/EDR back on is not allowed.
4797 *
4798 * Dual-mode controllers shall operate with the public
4799 * address as its identity address for BR/EDR and LE. So
4800 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004801 *
4802 * The same restrictions applies when secure connections
4803 * has been enabled. For BR/EDR this is a controller feature
4804 * while for LE it is a host stack feature. This means that
4805 * switching BR/EDR back on when secure connections has been
4806 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004807 */
4808 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004809 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4810 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004811 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4812 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004813 goto unlock;
4814 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004815 }
4816
4817 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004818 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4819 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004820 goto unlock;
4821 }
4822
4823 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4824 if (!cmd) {
4825 err = -ENOMEM;
4826 goto unlock;
4827 }
4828
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004829 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004830 * generates the correct flags.
4831 */
4832 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4833
4834 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004835
Johan Hedberg432df052014-08-01 11:13:31 +03004836 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004837 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004838
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004839 /* Since only the advertising data flags will change, there
4840 * is no need to update the scan response data.
4841 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004842 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004843
Johan Hedberg0663ca22013-10-02 13:43:14 +03004844 err = hci_req_run(&req, set_bredr_complete);
4845 if (err < 0)
4846 mgmt_pending_remove(cmd);
4847
4848unlock:
4849 hci_dev_unlock(hdev);
4850 return err;
4851}
4852
Johan Hedberga1443f52015-01-23 15:42:46 +02004853static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4854{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004855 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004856 struct mgmt_mode *cp;
4857
4858 BT_DBG("%s status %u", hdev->name, status);
4859
4860 hci_dev_lock(hdev);
4861
4862 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4863 if (!cmd)
4864 goto unlock;
4865
4866 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004867 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4868 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004869 goto remove;
4870 }
4871
4872 cp = cmd->param;
4873
4874 switch (cp->val) {
4875 case 0x00:
4876 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4877 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4878 break;
4879 case 0x01:
4880 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4881 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4882 break;
4883 case 0x02:
4884 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4885 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4886 break;
4887 }
4888
4889 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4890 new_settings(hdev, cmd->sk);
4891
4892remove:
4893 mgmt_pending_remove(cmd);
4894unlock:
4895 hci_dev_unlock(hdev);
4896}
4897
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004898static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4899 void *data, u16 len)
4900{
4901 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004902 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004903 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004904 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004905 int err;
4906
4907 BT_DBG("request for %s", hdev->name);
4908
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004909 if (!lmp_sc_capable(hdev) &&
4910 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004911 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4912 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004913
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004914 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004915 lmp_sc_capable(hdev) &&
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004916 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004917 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4918 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004919
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004920 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004921 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004922 MGMT_STATUS_INVALID_PARAMS);
4923
4924 hci_dev_lock(hdev);
4925
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004926 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004927 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004928 bool changed;
4929
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004930 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004931 changed = !test_and_set_bit(HCI_SC_ENABLED,
4932 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004933 if (cp->val == 0x02)
4934 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4935 else
4936 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4937 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004938 changed = test_and_clear_bit(HCI_SC_ENABLED,
4939 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004940 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4941 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004942
4943 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4944 if (err < 0)
4945 goto failed;
4946
4947 if (changed)
4948 err = new_settings(hdev, sk);
4949
4950 goto failed;
4951 }
4952
4953 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004954 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4955 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004956 goto failed;
4957 }
4958
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004959 val = !!cp->val;
4960
4961 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4962 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004963 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4964 goto failed;
4965 }
4966
4967 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4968 if (!cmd) {
4969 err = -ENOMEM;
4970 goto failed;
4971 }
4972
Johan Hedberga1443f52015-01-23 15:42:46 +02004973 hci_req_init(&req, hdev);
4974 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4975 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004976 if (err < 0) {
4977 mgmt_pending_remove(cmd);
4978 goto failed;
4979 }
4980
4981failed:
4982 hci_dev_unlock(hdev);
4983 return err;
4984}
4985
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004986static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4987 void *data, u16 len)
4988{
4989 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004990 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004991 int err;
4992
4993 BT_DBG("request for %s", hdev->name);
4994
Johan Hedbergb97109792014-06-24 14:00:28 +03004995 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004996 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4997 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004998
4999 hci_dev_lock(hdev);
5000
5001 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03005002 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
5003 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005004 else
Johan Hedberg0663b292014-06-24 13:15:50 +03005005 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
5006 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005007
Johan Hedbergb97109792014-06-24 14:00:28 +03005008 if (cp->val == 0x02)
5009 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
5010 &hdev->dev_flags);
5011 else
5012 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
5013 &hdev->dev_flags);
5014
5015 if (hdev_is_powered(hdev) && use_changed &&
5016 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
5017 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5018 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5019 sizeof(mode), &mode);
5020 }
5021
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005022 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5023 if (err < 0)
5024 goto unlock;
5025
5026 if (changed)
5027 err = new_settings(hdev, sk);
5028
5029unlock:
5030 hci_dev_unlock(hdev);
5031 return err;
5032}
5033
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005034static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5035 u16 len)
5036{
5037 struct mgmt_cp_set_privacy *cp = cp_data;
5038 bool changed;
5039 int err;
5040
5041 BT_DBG("request for %s", hdev->name);
5042
5043 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005044 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5045 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005046
5047 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005048 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5049 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005050
5051 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005052 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5053 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005054
5055 hci_dev_lock(hdev);
5056
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005057 /* If user space supports this command it is also expected to
5058 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5059 */
5060 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5061
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005062 if (cp->privacy) {
5063 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5064 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5065 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5066 } else {
5067 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5068 memset(hdev->irk, 0, sizeof(hdev->irk));
5069 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5070 }
5071
5072 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5073 if (err < 0)
5074 goto unlock;
5075
5076 if (changed)
5077 err = new_settings(hdev, sk);
5078
5079unlock:
5080 hci_dev_unlock(hdev);
5081 return err;
5082}
5083
Johan Hedberg41edf162014-02-18 10:19:35 +02005084static bool irk_is_valid(struct mgmt_irk_info *irk)
5085{
5086 switch (irk->addr.type) {
5087 case BDADDR_LE_PUBLIC:
5088 return true;
5089
5090 case BDADDR_LE_RANDOM:
5091 /* Two most significant bits shall be set */
5092 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5093 return false;
5094 return true;
5095 }
5096
5097 return false;
5098}
5099
5100static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5101 u16 len)
5102{
5103 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005104 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5105 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005106 u16 irk_count, expected_len;
5107 int i, err;
5108
5109 BT_DBG("request for %s", hdev->name);
5110
5111 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005112 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5113 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005114
5115 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005116 if (irk_count > max_irk_count) {
5117 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005118 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5119 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005120 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005121
5122 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5123 if (expected_len != len) {
5124 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005125 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005126 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5127 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005128 }
5129
5130 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5131
5132 for (i = 0; i < irk_count; i++) {
5133 struct mgmt_irk_info *key = &cp->irks[i];
5134
5135 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005136 return mgmt_cmd_status(sk, hdev->id,
5137 MGMT_OP_LOAD_IRKS,
5138 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005139 }
5140
5141 hci_dev_lock(hdev);
5142
5143 hci_smp_irks_clear(hdev);
5144
5145 for (i = 0; i < irk_count; i++) {
5146 struct mgmt_irk_info *irk = &cp->irks[i];
5147 u8 addr_type;
5148
5149 if (irk->addr.type == BDADDR_LE_PUBLIC)
5150 addr_type = ADDR_LE_DEV_PUBLIC;
5151 else
5152 addr_type = ADDR_LE_DEV_RANDOM;
5153
5154 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5155 BDADDR_ANY);
5156 }
5157
5158 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5159
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005160 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005161
5162 hci_dev_unlock(hdev);
5163
5164 return err;
5165}
5166
Johan Hedberg3f706b72013-01-20 14:27:16 +02005167static bool ltk_is_valid(struct mgmt_ltk_info *key)
5168{
5169 if (key->master != 0x00 && key->master != 0x01)
5170 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005171
5172 switch (key->addr.type) {
5173 case BDADDR_LE_PUBLIC:
5174 return true;
5175
5176 case BDADDR_LE_RANDOM:
5177 /* Two most significant bits shall be set */
5178 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5179 return false;
5180 return true;
5181 }
5182
5183 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005184}
5185
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005186static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005187 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005188{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005189 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005190 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5191 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005192 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005193 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005194
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005195 BT_DBG("request for %s", hdev->name);
5196
5197 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005198 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5199 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005200
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005201 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005202 if (key_count > max_key_count) {
5203 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005204 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5205 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005206 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005207
5208 expected_len = sizeof(*cp) + key_count *
5209 sizeof(struct mgmt_ltk_info);
5210 if (expected_len != len) {
5211 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005212 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005213 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5214 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005215 }
5216
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005217 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005218
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005219 for (i = 0; i < key_count; i++) {
5220 struct mgmt_ltk_info *key = &cp->keys[i];
5221
Johan Hedberg3f706b72013-01-20 14:27:16 +02005222 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005223 return mgmt_cmd_status(sk, hdev->id,
5224 MGMT_OP_LOAD_LONG_TERM_KEYS,
5225 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005226 }
5227
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005228 hci_dev_lock(hdev);
5229
5230 hci_smp_ltks_clear(hdev);
5231
5232 for (i = 0; i < key_count; i++) {
5233 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005234 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005235
5236 if (key->addr.type == BDADDR_LE_PUBLIC)
5237 addr_type = ADDR_LE_DEV_PUBLIC;
5238 else
5239 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005240
Johan Hedberg61b43352014-05-29 19:36:53 +03005241 switch (key->type) {
5242 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005243 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005244 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005245 break;
5246 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005247 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005248 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005249 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005250 case MGMT_LTK_P256_UNAUTH:
5251 authenticated = 0x00;
5252 type = SMP_LTK_P256;
5253 break;
5254 case MGMT_LTK_P256_AUTH:
5255 authenticated = 0x01;
5256 type = SMP_LTK_P256;
5257 break;
5258 case MGMT_LTK_P256_DEBUG:
5259 authenticated = 0x00;
5260 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005261 default:
5262 continue;
5263 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005264
Johan Hedberg35d70272014-02-19 14:57:47 +02005265 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005266 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005267 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005268 }
5269
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005270 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005271 NULL, 0);
5272
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005273 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005274
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005275 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005276}
5277
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005278static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005279{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005280 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005281 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005282 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005283
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005284 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005285
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005286 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005287 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005288 rp.tx_power = conn->tx_power;
5289 rp.max_tx_power = conn->max_tx_power;
5290 } else {
5291 rp.rssi = HCI_RSSI_INVALID;
5292 rp.tx_power = HCI_TX_POWER_INVALID;
5293 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005294 }
5295
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005296 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5297 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005298
5299 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005300 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005301
5302 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005303}
5304
Marcel Holtmann1904a852015-01-11 13:50:44 -08005305static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5306 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005307{
5308 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005309 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005310 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005311 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005312 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005313
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005314 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005315
5316 hci_dev_lock(hdev);
5317
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005318 /* Commands sent in request are either Read RSSI or Read Transmit Power
5319 * Level so we check which one was last sent to retrieve connection
5320 * handle. Both commands have handle as first parameter so it's safe to
5321 * cast data on the same command struct.
5322 *
5323 * First command sent is always Read RSSI and we fail only if it fails.
5324 * In other case we simply override error to indicate success as we
5325 * already remembered if TX power value is actually valid.
5326 */
5327 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5328 if (!cp) {
5329 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005330 status = MGMT_STATUS_SUCCESS;
5331 } else {
5332 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005333 }
5334
5335 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005336 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005337 goto unlock;
5338 }
5339
5340 handle = __le16_to_cpu(cp->handle);
5341 conn = hci_conn_hash_lookup_handle(hdev, handle);
5342 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005343 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005344 goto unlock;
5345 }
5346
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005347 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5348 if (!cmd)
5349 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005350
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005351 cmd->cmd_complete(cmd, status);
5352 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005353
5354unlock:
5355 hci_dev_unlock(hdev);
5356}
5357
5358static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5359 u16 len)
5360{
5361 struct mgmt_cp_get_conn_info *cp = data;
5362 struct mgmt_rp_get_conn_info rp;
5363 struct hci_conn *conn;
5364 unsigned long conn_info_age;
5365 int err = 0;
5366
5367 BT_DBG("%s", hdev->name);
5368
5369 memset(&rp, 0, sizeof(rp));
5370 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5371 rp.addr.type = cp->addr.type;
5372
5373 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005374 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5375 MGMT_STATUS_INVALID_PARAMS,
5376 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005377
5378 hci_dev_lock(hdev);
5379
5380 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005381 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5382 MGMT_STATUS_NOT_POWERED, &rp,
5383 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005384 goto unlock;
5385 }
5386
5387 if (cp->addr.type == BDADDR_BREDR)
5388 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5389 &cp->addr.bdaddr);
5390 else
5391 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5392
5393 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005394 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5395 MGMT_STATUS_NOT_CONNECTED, &rp,
5396 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005397 goto unlock;
5398 }
5399
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005400 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005401 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5402 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005403 goto unlock;
5404 }
5405
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005406 /* To avoid client trying to guess when to poll again for information we
5407 * calculate conn info age as random value between min/max set in hdev.
5408 */
5409 conn_info_age = hdev->conn_info_min_age +
5410 prandom_u32_max(hdev->conn_info_max_age -
5411 hdev->conn_info_min_age);
5412
5413 /* Query controller to refresh cached values if they are too old or were
5414 * never read.
5415 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005416 if (time_after(jiffies, conn->conn_info_timestamp +
5417 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005418 !conn->conn_info_timestamp) {
5419 struct hci_request req;
5420 struct hci_cp_read_tx_power req_txp_cp;
5421 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005422 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005423
5424 hci_req_init(&req, hdev);
5425 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5426 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5427 &req_rssi_cp);
5428
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005429 /* For LE links TX power does not change thus we don't need to
5430 * query for it once value is known.
5431 */
5432 if (!bdaddr_type_is_le(cp->addr.type) ||
5433 conn->tx_power == HCI_TX_POWER_INVALID) {
5434 req_txp_cp.handle = cpu_to_le16(conn->handle);
5435 req_txp_cp.type = 0x00;
5436 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5437 sizeof(req_txp_cp), &req_txp_cp);
5438 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005439
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005440 /* Max TX power needs to be read only once per connection */
5441 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5442 req_txp_cp.handle = cpu_to_le16(conn->handle);
5443 req_txp_cp.type = 0x01;
5444 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5445 sizeof(req_txp_cp), &req_txp_cp);
5446 }
5447
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005448 err = hci_req_run(&req, conn_info_refresh_complete);
5449 if (err < 0)
5450 goto unlock;
5451
5452 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5453 data, len);
5454 if (!cmd) {
5455 err = -ENOMEM;
5456 goto unlock;
5457 }
5458
5459 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005460 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005461 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005462
5463 conn->conn_info_timestamp = jiffies;
5464 } else {
5465 /* Cache is valid, just reply with values cached in hci_conn */
5466 rp.rssi = conn->rssi;
5467 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005468 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005469
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005470 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5471 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005472 }
5473
5474unlock:
5475 hci_dev_unlock(hdev);
5476 return err;
5477}
5478
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005479static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005480{
5481 struct hci_conn *conn = cmd->user_data;
5482 struct mgmt_rp_get_clock_info rp;
5483 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005484 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005485
5486 memset(&rp, 0, sizeof(rp));
5487 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5488
5489 if (status)
5490 goto complete;
5491
5492 hdev = hci_dev_get(cmd->index);
5493 if (hdev) {
5494 rp.local_clock = cpu_to_le32(hdev->clock);
5495 hci_dev_put(hdev);
5496 }
5497
5498 if (conn) {
5499 rp.piconet_clock = cpu_to_le32(conn->clock);
5500 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5501 }
5502
5503complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005504 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5505 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005506
5507 if (conn) {
5508 hci_conn_drop(conn);
5509 hci_conn_put(conn);
5510 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005511
5512 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005513}
5514
Marcel Holtmann1904a852015-01-11 13:50:44 -08005515static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005516{
Johan Hedberg95868422014-06-28 17:54:07 +03005517 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005518 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005519 struct hci_conn *conn;
5520
5521 BT_DBG("%s status %u", hdev->name, status);
5522
5523 hci_dev_lock(hdev);
5524
5525 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5526 if (!hci_cp)
5527 goto unlock;
5528
5529 if (hci_cp->which) {
5530 u16 handle = __le16_to_cpu(hci_cp->handle);
5531 conn = hci_conn_hash_lookup_handle(hdev, handle);
5532 } else {
5533 conn = NULL;
5534 }
5535
5536 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5537 if (!cmd)
5538 goto unlock;
5539
Johan Hedberg69487372014-12-05 13:36:07 +02005540 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005541 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005542
5543unlock:
5544 hci_dev_unlock(hdev);
5545}
5546
5547static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5548 u16 len)
5549{
5550 struct mgmt_cp_get_clock_info *cp = data;
5551 struct mgmt_rp_get_clock_info rp;
5552 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005553 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005554 struct hci_request req;
5555 struct hci_conn *conn;
5556 int err;
5557
5558 BT_DBG("%s", hdev->name);
5559
5560 memset(&rp, 0, sizeof(rp));
5561 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5562 rp.addr.type = cp->addr.type;
5563
5564 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005565 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5566 MGMT_STATUS_INVALID_PARAMS,
5567 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005568
5569 hci_dev_lock(hdev);
5570
5571 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005572 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5573 MGMT_STATUS_NOT_POWERED, &rp,
5574 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005575 goto unlock;
5576 }
5577
5578 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5579 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5580 &cp->addr.bdaddr);
5581 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005582 err = mgmt_cmd_complete(sk, hdev->id,
5583 MGMT_OP_GET_CLOCK_INFO,
5584 MGMT_STATUS_NOT_CONNECTED,
5585 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005586 goto unlock;
5587 }
5588 } else {
5589 conn = NULL;
5590 }
5591
5592 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5593 if (!cmd) {
5594 err = -ENOMEM;
5595 goto unlock;
5596 }
5597
Johan Hedberg69487372014-12-05 13:36:07 +02005598 cmd->cmd_complete = clock_info_cmd_complete;
5599
Johan Hedberg95868422014-06-28 17:54:07 +03005600 hci_req_init(&req, hdev);
5601
5602 memset(&hci_cp, 0, sizeof(hci_cp));
5603 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5604
5605 if (conn) {
5606 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005607 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005608
5609 hci_cp.handle = cpu_to_le16(conn->handle);
5610 hci_cp.which = 0x01; /* Piconet clock */
5611 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5612 }
5613
5614 err = hci_req_run(&req, get_clock_info_complete);
5615 if (err < 0)
5616 mgmt_pending_remove(cmd);
5617
5618unlock:
5619 hci_dev_unlock(hdev);
5620 return err;
5621}
5622
Johan Hedberg5a154e62014-12-19 22:26:02 +02005623static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5624{
5625 struct hci_conn *conn;
5626
5627 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5628 if (!conn)
5629 return false;
5630
5631 if (conn->dst_type != type)
5632 return false;
5633
5634 if (conn->state != BT_CONNECTED)
5635 return false;
5636
5637 return true;
5638}
5639
5640/* This function requires the caller holds hdev->lock */
5641static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5642 u8 addr_type, u8 auto_connect)
5643{
5644 struct hci_dev *hdev = req->hdev;
5645 struct hci_conn_params *params;
5646
5647 params = hci_conn_params_add(hdev, addr, addr_type);
5648 if (!params)
5649 return -EIO;
5650
5651 if (params->auto_connect == auto_connect)
5652 return 0;
5653
5654 list_del_init(&params->action);
5655
5656 switch (auto_connect) {
5657 case HCI_AUTO_CONN_DISABLED:
5658 case HCI_AUTO_CONN_LINK_LOSS:
5659 __hci_update_background_scan(req);
5660 break;
5661 case HCI_AUTO_CONN_REPORT:
5662 list_add(&params->action, &hdev->pend_le_reports);
5663 __hci_update_background_scan(req);
5664 break;
5665 case HCI_AUTO_CONN_DIRECT:
5666 case HCI_AUTO_CONN_ALWAYS:
5667 if (!is_connected(hdev, addr, addr_type)) {
5668 list_add(&params->action, &hdev->pend_le_conns);
5669 __hci_update_background_scan(req);
5670 }
5671 break;
5672 }
5673
5674 params->auto_connect = auto_connect;
5675
5676 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5677 auto_connect);
5678
5679 return 0;
5680}
5681
Marcel Holtmann8afef092014-06-29 22:28:34 +02005682static void device_added(struct sock *sk, struct hci_dev *hdev,
5683 bdaddr_t *bdaddr, u8 type, u8 action)
5684{
5685 struct mgmt_ev_device_added ev;
5686
5687 bacpy(&ev.addr.bdaddr, bdaddr);
5688 ev.addr.type = type;
5689 ev.action = action;
5690
5691 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5692}
5693
Marcel Holtmann1904a852015-01-11 13:50:44 -08005694static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005695{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005696 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005697
5698 BT_DBG("status 0x%02x", status);
5699
5700 hci_dev_lock(hdev);
5701
5702 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5703 if (!cmd)
5704 goto unlock;
5705
5706 cmd->cmd_complete(cmd, mgmt_status(status));
5707 mgmt_pending_remove(cmd);
5708
5709unlock:
5710 hci_dev_unlock(hdev);
5711}
5712
Marcel Holtmann2faade52014-06-29 19:44:03 +02005713static int add_device(struct sock *sk, struct hci_dev *hdev,
5714 void *data, u16 len)
5715{
5716 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005717 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005718 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005719 u8 auto_conn, addr_type;
5720 int err;
5721
5722 BT_DBG("%s", hdev->name);
5723
Johan Hedberg66593582014-07-09 12:59:14 +03005724 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005725 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005726 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5727 MGMT_STATUS_INVALID_PARAMS,
5728 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005729
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005730 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005731 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5732 MGMT_STATUS_INVALID_PARAMS,
5733 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005734
Johan Hedberg5a154e62014-12-19 22:26:02 +02005735 hci_req_init(&req, hdev);
5736
Marcel Holtmann2faade52014-06-29 19:44:03 +02005737 hci_dev_lock(hdev);
5738
Johan Hedberg5a154e62014-12-19 22:26:02 +02005739 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5740 if (!cmd) {
5741 err = -ENOMEM;
5742 goto unlock;
5743 }
5744
5745 cmd->cmd_complete = addr_cmd_complete;
5746
Johan Hedberg66593582014-07-09 12:59:14 +03005747 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005748 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005749 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005750 err = cmd->cmd_complete(cmd,
5751 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005752 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005753 goto unlock;
5754 }
5755
5756 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5757 cp->addr.type);
5758 if (err)
5759 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005760
Johan Hedberg5a154e62014-12-19 22:26:02 +02005761 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005762
Johan Hedberg66593582014-07-09 12:59:14 +03005763 goto added;
5764 }
5765
Marcel Holtmann2faade52014-06-29 19:44:03 +02005766 if (cp->addr.type == BDADDR_LE_PUBLIC)
5767 addr_type = ADDR_LE_DEV_PUBLIC;
5768 else
5769 addr_type = ADDR_LE_DEV_RANDOM;
5770
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005771 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005772 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005773 else if (cp->action == 0x01)
5774 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005775 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005776 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005777
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005778 /* If the connection parameters don't exist for this device,
5779 * they will be created and configured with defaults.
5780 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005781 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005782 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005783 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005784 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005785 goto unlock;
5786 }
5787
Johan Hedberg66593582014-07-09 12:59:14 +03005788added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005789 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5790
Johan Hedberg5a154e62014-12-19 22:26:02 +02005791 err = hci_req_run(&req, add_device_complete);
5792 if (err < 0) {
5793 /* ENODATA means no HCI commands were needed (e.g. if
5794 * the adapter is powered off).
5795 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005796 if (err == -ENODATA)
5797 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005798 mgmt_pending_remove(cmd);
5799 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005800
5801unlock:
5802 hci_dev_unlock(hdev);
5803 return err;
5804}
5805
Marcel Holtmann8afef092014-06-29 22:28:34 +02005806static void device_removed(struct sock *sk, struct hci_dev *hdev,
5807 bdaddr_t *bdaddr, u8 type)
5808{
5809 struct mgmt_ev_device_removed ev;
5810
5811 bacpy(&ev.addr.bdaddr, bdaddr);
5812 ev.addr.type = type;
5813
5814 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5815}
5816
Marcel Holtmann1904a852015-01-11 13:50:44 -08005817static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005818{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005819 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005820
5821 BT_DBG("status 0x%02x", status);
5822
5823 hci_dev_lock(hdev);
5824
5825 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5826 if (!cmd)
5827 goto unlock;
5828
5829 cmd->cmd_complete(cmd, mgmt_status(status));
5830 mgmt_pending_remove(cmd);
5831
5832unlock:
5833 hci_dev_unlock(hdev);
5834}
5835
Marcel Holtmann2faade52014-06-29 19:44:03 +02005836static int remove_device(struct sock *sk, struct hci_dev *hdev,
5837 void *data, u16 len)
5838{
5839 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005840 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005841 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005842 int err;
5843
5844 BT_DBG("%s", hdev->name);
5845
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005846 hci_req_init(&req, hdev);
5847
Marcel Holtmann2faade52014-06-29 19:44:03 +02005848 hci_dev_lock(hdev);
5849
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005850 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5851 if (!cmd) {
5852 err = -ENOMEM;
5853 goto unlock;
5854 }
5855
5856 cmd->cmd_complete = addr_cmd_complete;
5857
Marcel Holtmann2faade52014-06-29 19:44:03 +02005858 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005859 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005860 u8 addr_type;
5861
Johan Hedberg66593582014-07-09 12:59:14 +03005862 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005863 err = cmd->cmd_complete(cmd,
5864 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005865 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005866 goto unlock;
5867 }
5868
Johan Hedberg66593582014-07-09 12:59:14 +03005869 if (cp->addr.type == BDADDR_BREDR) {
5870 err = hci_bdaddr_list_del(&hdev->whitelist,
5871 &cp->addr.bdaddr,
5872 cp->addr.type);
5873 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005874 err = cmd->cmd_complete(cmd,
5875 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005876 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005877 goto unlock;
5878 }
5879
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005880 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005881
Johan Hedberg66593582014-07-09 12:59:14 +03005882 device_removed(sk, hdev, &cp->addr.bdaddr,
5883 cp->addr.type);
5884 goto complete;
5885 }
5886
Marcel Holtmann2faade52014-06-29 19:44:03 +02005887 if (cp->addr.type == BDADDR_LE_PUBLIC)
5888 addr_type = ADDR_LE_DEV_PUBLIC;
5889 else
5890 addr_type = ADDR_LE_DEV_RANDOM;
5891
Johan Hedbergc71593d2014-07-02 17:37:28 +03005892 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5893 addr_type);
5894 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005895 err = cmd->cmd_complete(cmd,
5896 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005897 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005898 goto unlock;
5899 }
5900
5901 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005902 err = cmd->cmd_complete(cmd,
5903 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005904 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005905 goto unlock;
5906 }
5907
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005908 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005909 list_del(&params->list);
5910 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005911 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005912
5913 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005914 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005915 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005916 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005917
Marcel Holtmann2faade52014-06-29 19:44:03 +02005918 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005919 err = cmd->cmd_complete(cmd,
5920 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005921 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005922 goto unlock;
5923 }
5924
Johan Hedberg66593582014-07-09 12:59:14 +03005925 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5926 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5927 list_del(&b->list);
5928 kfree(b);
5929 }
5930
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005931 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005932
Johan Hedberg19de0822014-07-06 13:06:51 +03005933 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5934 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5935 continue;
5936 device_removed(sk, hdev, &p->addr, p->addr_type);
5937 list_del(&p->action);
5938 list_del(&p->list);
5939 kfree(p);
5940 }
5941
5942 BT_DBG("All LE connection parameters were removed");
5943
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005944 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005945 }
5946
Johan Hedberg66593582014-07-09 12:59:14 +03005947complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005948 err = hci_req_run(&req, remove_device_complete);
5949 if (err < 0) {
5950 /* ENODATA means no HCI commands were needed (e.g. if
5951 * the adapter is powered off).
5952 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005953 if (err == -ENODATA)
5954 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005955 mgmt_pending_remove(cmd);
5956 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005957
5958unlock:
5959 hci_dev_unlock(hdev);
5960 return err;
5961}
5962
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005963static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5964 u16 len)
5965{
5966 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005967 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5968 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005969 u16 param_count, expected_len;
5970 int i;
5971
5972 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005973 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5974 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005975
5976 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005977 if (param_count > max_param_count) {
5978 BT_ERR("load_conn_param: too big param_count value %u",
5979 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005980 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5981 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005982 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005983
5984 expected_len = sizeof(*cp) + param_count *
5985 sizeof(struct mgmt_conn_param);
5986 if (expected_len != len) {
5987 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5988 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005989 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5990 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005991 }
5992
5993 BT_DBG("%s param_count %u", hdev->name, param_count);
5994
5995 hci_dev_lock(hdev);
5996
5997 hci_conn_params_clear_disabled(hdev);
5998
5999 for (i = 0; i < param_count; i++) {
6000 struct mgmt_conn_param *param = &cp->params[i];
6001 struct hci_conn_params *hci_param;
6002 u16 min, max, latency, timeout;
6003 u8 addr_type;
6004
6005 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6006 param->addr.type);
6007
6008 if (param->addr.type == BDADDR_LE_PUBLIC) {
6009 addr_type = ADDR_LE_DEV_PUBLIC;
6010 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6011 addr_type = ADDR_LE_DEV_RANDOM;
6012 } else {
6013 BT_ERR("Ignoring invalid connection parameters");
6014 continue;
6015 }
6016
6017 min = le16_to_cpu(param->min_interval);
6018 max = le16_to_cpu(param->max_interval);
6019 latency = le16_to_cpu(param->latency);
6020 timeout = le16_to_cpu(param->timeout);
6021
6022 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6023 min, max, latency, timeout);
6024
6025 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6026 BT_ERR("Ignoring invalid connection parameters");
6027 continue;
6028 }
6029
6030 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6031 addr_type);
6032 if (!hci_param) {
6033 BT_ERR("Failed to add connection parameters");
6034 continue;
6035 }
6036
6037 hci_param->conn_min_interval = min;
6038 hci_param->conn_max_interval = max;
6039 hci_param->conn_latency = latency;
6040 hci_param->supervision_timeout = timeout;
6041 }
6042
6043 hci_dev_unlock(hdev);
6044
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006045 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6046 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006047}
6048
Marcel Holtmanndbece372014-07-04 18:11:55 +02006049static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6050 void *data, u16 len)
6051{
6052 struct mgmt_cp_set_external_config *cp = data;
6053 bool changed;
6054 int err;
6055
6056 BT_DBG("%s", hdev->name);
6057
6058 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006059 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6060 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006061
6062 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006063 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6064 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006065
6066 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006067 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6068 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006069
6070 hci_dev_lock(hdev);
6071
6072 if (cp->config)
6073 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6074 &hdev->dev_flags);
6075 else
6076 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6077 &hdev->dev_flags);
6078
6079 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6080 if (err < 0)
6081 goto unlock;
6082
6083 if (!changed)
6084 goto unlock;
6085
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006086 err = new_options(hdev, sk);
6087
Marcel Holtmanndbece372014-07-04 18:11:55 +02006088 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
6089 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006090
6091 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6092 set_bit(HCI_CONFIG, &hdev->dev_flags);
6093 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6094
6095 queue_work(hdev->req_workqueue, &hdev->power_on);
6096 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006097 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006098 mgmt_index_added(hdev);
6099 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006100 }
6101
6102unlock:
6103 hci_dev_unlock(hdev);
6104 return err;
6105}
6106
Marcel Holtmann9713c172014-07-06 12:11:15 +02006107static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6108 void *data, u16 len)
6109{
6110 struct mgmt_cp_set_public_address *cp = data;
6111 bool changed;
6112 int err;
6113
6114 BT_DBG("%s", hdev->name);
6115
6116 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006117 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6118 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006119
6120 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006121 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6122 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006123
6124 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006125 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6126 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006127
6128 hci_dev_lock(hdev);
6129
6130 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6131 bacpy(&hdev->public_addr, &cp->bdaddr);
6132
6133 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6134 if (err < 0)
6135 goto unlock;
6136
6137 if (!changed)
6138 goto unlock;
6139
6140 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6141 err = new_options(hdev, sk);
6142
6143 if (is_configured(hdev)) {
6144 mgmt_index_removed(hdev);
6145
6146 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6147
6148 set_bit(HCI_CONFIG, &hdev->dev_flags);
6149 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6150
6151 queue_work(hdev->req_workqueue, &hdev->power_on);
6152 }
6153
6154unlock:
6155 hci_dev_unlock(hdev);
6156 return err;
6157}
6158
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006159static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006160 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006161 { read_version, MGMT_READ_VERSION_SIZE,
6162 HCI_MGMT_NO_HDEV },
6163 { read_commands, MGMT_READ_COMMANDS_SIZE,
6164 HCI_MGMT_NO_HDEV },
6165 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6166 HCI_MGMT_NO_HDEV },
6167 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6168 { set_powered, MGMT_SETTING_SIZE, 0 },
6169 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6170 { set_connectable, MGMT_SETTING_SIZE, 0 },
6171 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6172 { set_bondable, MGMT_SETTING_SIZE, 0 },
6173 { set_link_security, MGMT_SETTING_SIZE, 0 },
6174 { set_ssp, MGMT_SETTING_SIZE, 0 },
6175 { set_hs, MGMT_SETTING_SIZE, 0 },
6176 { set_le, MGMT_SETTING_SIZE, 0 },
6177 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6178 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6179 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6180 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6181 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6182 HCI_MGMT_VAR_LEN },
6183 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6184 HCI_MGMT_VAR_LEN },
6185 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6186 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6187 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6188 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6189 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6190 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6191 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6192 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6193 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6194 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6195 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6196 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6197 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6198 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6199 HCI_MGMT_VAR_LEN },
6200 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6201 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6202 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6203 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6204 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6205 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6206 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6207 { set_advertising, MGMT_SETTING_SIZE, 0 },
6208 { set_bredr, MGMT_SETTING_SIZE, 0 },
6209 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6210 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6211 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6212 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6213 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6214 { load_irks, MGMT_LOAD_IRKS_SIZE,
6215 HCI_MGMT_VAR_LEN },
6216 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6217 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6218 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6219 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6220 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6221 HCI_MGMT_VAR_LEN },
6222 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6223 HCI_MGMT_NO_HDEV },
6224 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6225 HCI_MGMT_UNCONFIGURED },
6226 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6227 HCI_MGMT_UNCONFIGURED },
6228 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6229 HCI_MGMT_UNCONFIGURED },
6230 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6231 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006232};
6233
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006234int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6235 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006236{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006237 void *buf;
6238 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006239 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006240 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006241 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006242 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006243 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006244 int err;
6245
6246 BT_DBG("got %zu bytes", msglen);
6247
6248 if (msglen < sizeof(*hdr))
6249 return -EINVAL;
6250
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006251 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006252 if (!buf)
6253 return -ENOMEM;
6254
Al Viro6ce8e9c2014-04-06 21:25:44 -04006255 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006256 err = -EFAULT;
6257 goto done;
6258 }
6259
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006260 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006261 opcode = __le16_to_cpu(hdr->opcode);
6262 index = __le16_to_cpu(hdr->index);
6263 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006264
6265 if (len != msglen - sizeof(*hdr)) {
6266 err = -EINVAL;
6267 goto done;
6268 }
6269
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006270 if (opcode >= chan->handler_count ||
6271 chan->handlers[opcode].func == NULL) {
6272 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006273 err = mgmt_cmd_status(sk, index, opcode,
6274 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006275 goto done;
6276 }
6277
6278 handler = &chan->handlers[opcode];
6279
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006280 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006281 hdev = hci_dev_get(index);
6282 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006283 err = mgmt_cmd_status(sk, index, opcode,
6284 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006285 goto done;
6286 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006287
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006288 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006289 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006290 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006291 err = mgmt_cmd_status(sk, index, opcode,
6292 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006293 goto done;
6294 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006295
6296 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006297 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006298 err = mgmt_cmd_status(sk, index, opcode,
6299 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006300 goto done;
6301 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006302 }
6303
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006304 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6305 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006306 err = mgmt_cmd_status(sk, index, opcode,
6307 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006308 goto done;
6309 }
6310
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006311 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6312 if ((var_len && len < handler->data_len) ||
6313 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006314 err = mgmt_cmd_status(sk, index, opcode,
6315 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006316 goto done;
6317 }
6318
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006319 if (hdev)
6320 mgmt_init_hdev(sk, hdev);
6321
6322 cp = buf + sizeof(*hdr);
6323
Johan Hedbergbe22b542012-03-01 22:24:41 +02006324 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006325 if (err < 0)
6326 goto done;
6327
Johan Hedberg03811012010-12-08 00:21:06 +02006328 err = msglen;
6329
6330done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006331 if (hdev)
6332 hci_dev_put(hdev);
6333
Johan Hedberg03811012010-12-08 00:21:06 +02006334 kfree(buf);
6335 return err;
6336}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006337
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006338void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006339{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006340 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006341 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006342
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006343 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6344 return;
6345
6346 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6347 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6348 else
6349 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006350}
6351
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006352void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006353{
Johan Hedberg5f159032012-03-02 03:13:19 +02006354 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006355
Marcel Holtmann1514b892013-10-06 08:25:01 -07006356 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006357 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006358
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006359 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6360 return;
6361
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006362 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006363
Marcel Holtmannedd38962014-07-02 21:30:55 +02006364 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6365 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6366 else
6367 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006368}
6369
Andre Guedes6046dc32014-02-26 20:21:51 -03006370/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006371static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006372{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006373 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006374 struct hci_conn_params *p;
6375
6376 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006377 /* Needed for AUTO_OFF case where might not "really"
6378 * have been powered off.
6379 */
6380 list_del_init(&p->action);
6381
6382 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006383 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006384 case HCI_AUTO_CONN_ALWAYS:
6385 list_add(&p->action, &hdev->pend_le_conns);
6386 break;
6387 case HCI_AUTO_CONN_REPORT:
6388 list_add(&p->action, &hdev->pend_le_reports);
6389 break;
6390 default:
6391 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006392 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006393 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006394
Johan Hedberg2cf22212014-12-19 22:26:00 +02006395 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006396}
6397
Marcel Holtmann1904a852015-01-11 13:50:44 -08006398static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006399{
6400 struct cmd_lookup match = { NULL, hdev };
6401
6402 BT_DBG("status 0x%02x", status);
6403
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006404 if (!status) {
6405 /* Register the available SMP channels (BR/EDR and LE) only
6406 * when successfully powering on the controller. This late
6407 * registration is required so that LE SMP can clearly
6408 * decide if the public address or static address is used.
6409 */
6410 smp_register(hdev);
6411 }
6412
Johan Hedberg229ab392013-03-15 17:06:53 -05006413 hci_dev_lock(hdev);
6414
6415 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6416
6417 new_settings(hdev, match.sk);
6418
6419 hci_dev_unlock(hdev);
6420
6421 if (match.sk)
6422 sock_put(match.sk);
6423}
6424
Johan Hedberg70da6242013-03-15 17:06:51 -05006425static int powered_update_hci(struct hci_dev *hdev)
6426{
Johan Hedberg890ea892013-03-15 17:06:52 -05006427 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006428 u8 link_sec;
6429
Johan Hedberg890ea892013-03-15 17:06:52 -05006430 hci_req_init(&req, hdev);
6431
Johan Hedberg70da6242013-03-15 17:06:51 -05006432 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6433 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006434 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006435
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006436 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006437
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006438 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6439 u8 support = 0x01;
6440
6441 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6442 sizeof(support), &support);
6443 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006444 }
6445
Johan Hedbergc73eee92013-04-19 18:35:21 +03006446 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6447 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006448 struct hci_cp_write_le_host_supported cp;
6449
Marcel Holtmann32226e42014-07-24 20:04:16 +02006450 cp.le = 0x01;
6451 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006452
6453 /* Check first if we already have the right
6454 * host state (host features set)
6455 */
6456 if (cp.le != lmp_host_le_capable(hdev) ||
6457 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006458 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6459 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006460 }
6461
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006462 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006463 /* Make sure the controller has a good default for
6464 * advertising data. This also applies to the case
6465 * where BR/EDR was toggled during the AUTO_OFF phase.
6466 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006467 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006468 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006469 update_scan_rsp_data(&req);
6470 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006471
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006472 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6473 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006474
6475 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006476 }
6477
Johan Hedberg70da6242013-03-15 17:06:51 -05006478 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6479 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006480 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6481 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006482
6483 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006484 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006485 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006486 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006487 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006488 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006489 }
6490
Johan Hedberg229ab392013-03-15 17:06:53 -05006491 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006492}
6493
Johan Hedberg744cf192011-11-08 20:40:14 +02006494int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006495{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006496 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006497 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006498 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006499
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006500 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6501 return 0;
6502
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006503 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006504 if (powered_update_hci(hdev) == 0)
6505 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006506
Johan Hedberg229ab392013-03-15 17:06:53 -05006507 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6508 &match);
6509 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006510 }
6511
Johan Hedberg229ab392013-03-15 17:06:53 -05006512 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006513
6514 /* If the power off is because of hdev unregistration let
6515 * use the appropriate INVALID_INDEX status. Otherwise use
6516 * NOT_POWERED. We cover both scenarios here since later in
6517 * mgmt_index_removed() any hci_conn callbacks will have already
6518 * been triggered, potentially causing misleading DISCONNECTED
6519 * status responses.
6520 */
6521 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6522 status = MGMT_STATUS_INVALID_INDEX;
6523 else
6524 status = MGMT_STATUS_NOT_POWERED;
6525
6526 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006527
6528 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6529 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6530 zero_cod, sizeof(zero_cod), NULL);
6531
6532new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006533 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006534
6535 if (match.sk)
6536 sock_put(match.sk);
6537
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006538 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006539}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006540
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006541void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006542{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006543 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006544 u8 status;
6545
6546 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6547 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006548 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006549
6550 if (err == -ERFKILL)
6551 status = MGMT_STATUS_RFKILLED;
6552 else
6553 status = MGMT_STATUS_FAILED;
6554
Johan Hedberga69e8372015-03-06 21:08:53 +02006555 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006556
6557 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006558}
6559
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006560void mgmt_discoverable_timeout(struct hci_dev *hdev)
6561{
6562 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006563
6564 hci_dev_lock(hdev);
6565
6566 /* When discoverable timeout triggers, then just make sure
6567 * the limited discoverable flag is cleared. Even in the case
6568 * of a timeout triggered from general discoverable, it is
6569 * safe to unconditionally clear the flag.
6570 */
6571 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006572 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006573
6574 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006575 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6576 u8 scan = SCAN_PAGE;
6577 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6578 sizeof(scan), &scan);
6579 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006580 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006581 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006582 hci_req_run(&req, NULL);
6583
6584 hdev->discov_timeout = 0;
6585
Johan Hedberg9a43e252013-10-20 19:00:07 +03006586 new_settings(hdev, NULL);
6587
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006588 hci_dev_unlock(hdev);
6589}
6590
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006591void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6592 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006593{
Johan Hedberg86742e12011-11-07 23:13:38 +02006594 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006595
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006596 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006597
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006598 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006599 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006600 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006601 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006602 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006603 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006604
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006605 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006606}
Johan Hedbergf7520542011-01-20 12:34:39 +02006607
Johan Hedbergd7b25452014-05-23 13:19:53 +03006608static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6609{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006610 switch (ltk->type) {
6611 case SMP_LTK:
6612 case SMP_LTK_SLAVE:
6613 if (ltk->authenticated)
6614 return MGMT_LTK_AUTHENTICATED;
6615 return MGMT_LTK_UNAUTHENTICATED;
6616 case SMP_LTK_P256:
6617 if (ltk->authenticated)
6618 return MGMT_LTK_P256_AUTH;
6619 return MGMT_LTK_P256_UNAUTH;
6620 case SMP_LTK_P256_DEBUG:
6621 return MGMT_LTK_P256_DEBUG;
6622 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006623
6624 return MGMT_LTK_UNAUTHENTICATED;
6625}
6626
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006627void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006628{
6629 struct mgmt_ev_new_long_term_key ev;
6630
6631 memset(&ev, 0, sizeof(ev));
6632
Marcel Holtmann5192d302014-02-19 17:11:58 -08006633 /* Devices using resolvable or non-resolvable random addresses
6634 * without providing an indentity resolving key don't require
6635 * to store long term keys. Their addresses will change the
6636 * next time around.
6637 *
6638 * Only when a remote device provides an identity address
6639 * make sure the long term key is stored. If the remote
6640 * identity is known, the long term keys are internally
6641 * mapped to the identity address. So allow static random
6642 * and public addresses here.
6643 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006644 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6645 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6646 ev.store_hint = 0x00;
6647 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006648 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006649
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006650 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006651 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006652 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006653 ev.key.enc_size = key->enc_size;
6654 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006655 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006656
Johan Hedberg2ceba532014-06-16 19:25:16 +03006657 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006658 ev.key.master = 1;
6659
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006660 memcpy(ev.key.val, key->val, sizeof(key->val));
6661
Marcel Holtmann083368f2013-10-15 14:26:29 -07006662 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006663}
6664
Johan Hedberg95fbac82014-02-19 15:18:31 +02006665void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6666{
6667 struct mgmt_ev_new_irk ev;
6668
6669 memset(&ev, 0, sizeof(ev));
6670
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006671 /* For identity resolving keys from devices that are already
6672 * using a public address or static random address, do not
6673 * ask for storing this key. The identity resolving key really
6674 * is only mandatory for devices using resovlable random
6675 * addresses.
6676 *
6677 * Storing all identity resolving keys has the downside that
6678 * they will be also loaded on next boot of they system. More
6679 * identity resolving keys, means more time during scanning is
6680 * needed to actually resolve these addresses.
6681 */
6682 if (bacmp(&irk->rpa, BDADDR_ANY))
6683 ev.store_hint = 0x01;
6684 else
6685 ev.store_hint = 0x00;
6686
Johan Hedberg95fbac82014-02-19 15:18:31 +02006687 bacpy(&ev.rpa, &irk->rpa);
6688 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6689 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6690 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6691
6692 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6693}
6694
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006695void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6696 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006697{
6698 struct mgmt_ev_new_csrk ev;
6699
6700 memset(&ev, 0, sizeof(ev));
6701
6702 /* Devices using resolvable or non-resolvable random addresses
6703 * without providing an indentity resolving key don't require
6704 * to store signature resolving keys. Their addresses will change
6705 * the next time around.
6706 *
6707 * Only when a remote device provides an identity address
6708 * make sure the signature resolving key is stored. So allow
6709 * static random and public addresses here.
6710 */
6711 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6712 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6713 ev.store_hint = 0x00;
6714 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006715 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006716
6717 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6718 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006719 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006720 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6721
6722 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6723}
6724
Andre Guedesffb5a8272014-07-01 18:10:11 -03006725void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006726 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6727 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006728{
6729 struct mgmt_ev_new_conn_param ev;
6730
Johan Hedbergc103aea2014-07-02 17:37:34 +03006731 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6732 return;
6733
Andre Guedesffb5a8272014-07-01 18:10:11 -03006734 memset(&ev, 0, sizeof(ev));
6735 bacpy(&ev.addr.bdaddr, bdaddr);
6736 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006737 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006738 ev.min_interval = cpu_to_le16(min_interval);
6739 ev.max_interval = cpu_to_le16(max_interval);
6740 ev.latency = cpu_to_le16(latency);
6741 ev.timeout = cpu_to_le16(timeout);
6742
6743 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6744}
6745
Marcel Holtmann94933992013-10-15 10:26:39 -07006746static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6747 u8 data_len)
6748{
6749 eir[eir_len++] = sizeof(type) + data_len;
6750 eir[eir_len++] = type;
6751 memcpy(&eir[eir_len], data, data_len);
6752 eir_len += data_len;
6753
6754 return eir_len;
6755}
6756
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006757void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6758 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006759{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006760 char buf[512];
6761 struct mgmt_ev_device_connected *ev = (void *) buf;
6762 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006763
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006764 bacpy(&ev->addr.bdaddr, &conn->dst);
6765 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006766
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006767 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006768
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006769 /* We must ensure that the EIR Data fields are ordered and
6770 * unique. Keep it simple for now and avoid the problem by not
6771 * adding any BR/EDR data to the LE adv.
6772 */
6773 if (conn->le_adv_data_len > 0) {
6774 memcpy(&ev->eir[eir_len],
6775 conn->le_adv_data, conn->le_adv_data_len);
6776 eir_len = conn->le_adv_data_len;
6777 } else {
6778 if (name_len > 0)
6779 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6780 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006781
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006782 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006783 eir_len = eir_append_data(ev->eir, eir_len,
6784 EIR_CLASS_OF_DEV,
6785 conn->dev_class, 3);
6786 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006787
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006788 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006789
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006790 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6791 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006792}
6793
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006794static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006795{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006796 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006797
Johan Hedbergf5818c22014-12-05 13:36:02 +02006798 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006799
6800 *sk = cmd->sk;
6801 sock_hold(*sk);
6802
Johan Hedberga664b5b2011-02-19 12:06:02 -03006803 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006804}
6805
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006806static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006807{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006808 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006809 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006810
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006811 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6812
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006813 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006814 mgmt_pending_remove(cmd);
6815}
6816
Johan Hedberg84c61d92014-08-01 11:13:30 +03006817bool mgmt_powering_down(struct hci_dev *hdev)
6818{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006819 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006820 struct mgmt_mode *cp;
6821
6822 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6823 if (!cmd)
6824 return false;
6825
6826 cp = cmd->param;
6827 if (!cp->val)
6828 return true;
6829
6830 return false;
6831}
6832
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006833void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006834 u8 link_type, u8 addr_type, u8 reason,
6835 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006836{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006837 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006838 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006839
Johan Hedberg84c61d92014-08-01 11:13:30 +03006840 /* The connection is still in hci_conn_hash so test for 1
6841 * instead of 0 to know if this is the last one.
6842 */
6843 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6844 cancel_delayed_work(&hdev->power_off);
6845 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006846 }
6847
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006848 if (!mgmt_connected)
6849 return;
6850
Andre Guedes57eb7762013-10-30 19:01:41 -03006851 if (link_type != ACL_LINK && link_type != LE_LINK)
6852 return;
6853
Johan Hedberg744cf192011-11-08 20:40:14 +02006854 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006855
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006856 bacpy(&ev.addr.bdaddr, bdaddr);
6857 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6858 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006859
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006860 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006861
6862 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006863 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006864
Johan Hedberg124f6e32012-02-09 13:50:12 +02006865 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006866 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006867}
6868
Marcel Holtmann78929242013-10-06 23:55:47 -07006869void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6870 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006871{
Andre Guedes3655bba2013-10-30 19:01:40 -03006872 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6873 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006874 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006875
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006876 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6877 hdev);
6878
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006879 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006880 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006881 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006882
Andre Guedes3655bba2013-10-30 19:01:40 -03006883 cp = cmd->param;
6884
6885 if (bacmp(bdaddr, &cp->addr.bdaddr))
6886 return;
6887
6888 if (cp->addr.type != bdaddr_type)
6889 return;
6890
Johan Hedbergf5818c22014-12-05 13:36:02 +02006891 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006892 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006893}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006894
Marcel Holtmann445608d2013-10-06 23:55:48 -07006895void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6896 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006897{
6898 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006899
Johan Hedberg84c61d92014-08-01 11:13:30 +03006900 /* The connection is still in hci_conn_hash so test for 1
6901 * instead of 0 to know if this is the last one.
6902 */
6903 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6904 cancel_delayed_work(&hdev->power_off);
6905 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006906 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006907
Johan Hedberg4c659c32011-11-07 23:13:39 +02006908 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006909 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006910 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006911
Marcel Holtmann445608d2013-10-06 23:55:48 -07006912 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006913}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006914
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006915void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006916{
6917 struct mgmt_ev_pin_code_request ev;
6918
Johan Hedbergd8457692012-02-17 14:24:57 +02006919 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006920 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006921 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006922
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006923 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006924}
6925
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006926void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6927 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006928{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006929 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006930
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006931 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006932 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006933 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006934
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006935 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006936 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006937}
6938
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006939void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6940 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006941{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006942 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006943
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006944 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006945 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006946 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006947
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006948 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006949 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006950}
Johan Hedberga5c29682011-02-19 12:05:57 -03006951
Johan Hedberg744cf192011-11-08 20:40:14 +02006952int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006953 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006954 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006955{
6956 struct mgmt_ev_user_confirm_request ev;
6957
Johan Hedberg744cf192011-11-08 20:40:14 +02006958 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006959
Johan Hedberg272d90d2012-02-09 15:26:12 +02006960 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006961 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006962 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006963 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006964
Johan Hedberg744cf192011-11-08 20:40:14 +02006965 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006966 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006967}
6968
Johan Hedberg272d90d2012-02-09 15:26:12 +02006969int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006970 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006971{
6972 struct mgmt_ev_user_passkey_request ev;
6973
6974 BT_DBG("%s", hdev->name);
6975
Johan Hedberg272d90d2012-02-09 15:26:12 +02006976 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006977 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006978
6979 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006980 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006981}
6982
Brian Gix0df4c182011-11-16 13:53:13 -08006983static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006984 u8 link_type, u8 addr_type, u8 status,
6985 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006986{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006987 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006988
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006989 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006990 if (!cmd)
6991 return -ENOENT;
6992
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006993 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006994 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006995
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006996 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006997}
6998
Johan Hedberg744cf192011-11-08 20:40:14 +02006999int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007000 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007001{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007002 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007003 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007004}
7005
Johan Hedberg272d90d2012-02-09 15:26:12 +02007006int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007007 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007008{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007009 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007010 status,
7011 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007012}
Johan Hedberg2a611692011-02-19 12:06:00 -03007013
Brian Gix604086b2011-11-23 08:28:33 -08007014int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007015 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007016{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007017 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007018 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007019}
7020
Johan Hedberg272d90d2012-02-09 15:26:12 +02007021int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007022 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007023{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007024 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007025 status,
7026 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007027}
7028
Johan Hedberg92a25252012-09-06 18:39:26 +03007029int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7030 u8 link_type, u8 addr_type, u32 passkey,
7031 u8 entered)
7032{
7033 struct mgmt_ev_passkey_notify ev;
7034
7035 BT_DBG("%s", hdev->name);
7036
7037 bacpy(&ev.addr.bdaddr, bdaddr);
7038 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7039 ev.passkey = __cpu_to_le32(passkey);
7040 ev.entered = entered;
7041
7042 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7043}
7044
Johan Hedberge1e930f2014-09-08 17:09:49 -07007045void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007046{
7047 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007048 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007049 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007050
Johan Hedberge1e930f2014-09-08 17:09:49 -07007051 bacpy(&ev.addr.bdaddr, &conn->dst);
7052 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7053 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007054
Johan Hedberge1e930f2014-09-08 17:09:49 -07007055 cmd = find_pairing(conn);
7056
7057 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7058 cmd ? cmd->sk : NULL);
7059
Johan Hedberga511b352014-12-11 21:45:45 +02007060 if (cmd) {
7061 cmd->cmd_complete(cmd, status);
7062 mgmt_pending_remove(cmd);
7063 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007064}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007065
Marcel Holtmann464996a2013-10-15 14:26:24 -07007066void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007067{
7068 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007069 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007070
7071 if (status) {
7072 u8 mgmt_err = mgmt_status(status);
7073 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007074 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007075 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007076 }
7077
Marcel Holtmann464996a2013-10-15 14:26:24 -07007078 if (test_bit(HCI_AUTH, &hdev->flags))
7079 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7080 &hdev->dev_flags);
7081 else
7082 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7083 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007084
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007085 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007086 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007087
Johan Hedberg47990ea2012-02-22 11:58:37 +02007088 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007089 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007090
7091 if (match.sk)
7092 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007093}
7094
Johan Hedberg890ea892013-03-15 17:06:52 -05007095static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007096{
Johan Hedberg890ea892013-03-15 17:06:52 -05007097 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007098 struct hci_cp_write_eir cp;
7099
Johan Hedberg976eb202012-10-24 21:12:01 +03007100 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007101 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007102
Johan Hedbergc80da272012-02-22 15:38:48 +02007103 memset(hdev->eir, 0, sizeof(hdev->eir));
7104
Johan Hedbergcacaf522012-02-21 00:52:42 +02007105 memset(&cp, 0, sizeof(cp));
7106
Johan Hedberg890ea892013-03-15 17:06:52 -05007107 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007108}
7109
Marcel Holtmann3e248562013-10-15 14:26:25 -07007110void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007111{
7112 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007113 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007114 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007115
7116 if (status) {
7117 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007118
7119 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007120 &hdev->dev_flags)) {
7121 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007122 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007123 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007124
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007125 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7126 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007127 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007128 }
7129
7130 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007131 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007132 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007133 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7134 if (!changed)
7135 changed = test_and_clear_bit(HCI_HS_ENABLED,
7136 &hdev->dev_flags);
7137 else
7138 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007139 }
7140
7141 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7142
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007143 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007144 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007145
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007146 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007147 sock_put(match.sk);
7148
Johan Hedberg890ea892013-03-15 17:06:52 -05007149 hci_req_init(&req, hdev);
7150
Johan Hedberg37699722014-06-24 14:00:27 +03007151 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
7152 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
7153 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7154 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007155 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007156 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007157 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007158 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007159
7160 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007161}
7162
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007163static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007164{
7165 struct cmd_lookup *match = data;
7166
Johan Hedberg90e70452012-02-23 23:09:40 +02007167 if (match->sk == NULL) {
7168 match->sk = cmd->sk;
7169 sock_hold(match->sk);
7170 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007171}
7172
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007173void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7174 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007175{
Johan Hedberg90e70452012-02-23 23:09:40 +02007176 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007177
Johan Hedberg92da6092013-03-15 17:06:55 -05007178 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7179 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7180 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007181
7182 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007183 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7184 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007185
7186 if (match.sk)
7187 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007188}
7189
Marcel Holtmann7667da32013-10-15 14:26:27 -07007190void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007191{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007192 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007193 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007194
Johan Hedberg13928972013-03-15 17:07:00 -05007195 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007196 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007197
7198 memset(&ev, 0, sizeof(ev));
7199 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007200 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007201
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007202 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007203 if (!cmd) {
7204 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007205
Johan Hedberg13928972013-03-15 17:07:00 -05007206 /* If this is a HCI command related to powering on the
7207 * HCI dev don't send any mgmt signals.
7208 */
7209 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007210 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007211 }
7212
Marcel Holtmann7667da32013-10-15 14:26:27 -07007213 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7214 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007215}
Szymon Jancc35938b2011-03-22 13:12:21 +01007216
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007217void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007218 u8 *rand192, u8 *hash256, u8 *rand256,
7219 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007220{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007221 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007222
Johan Hedberg744cf192011-11-08 20:40:14 +02007223 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007224
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007225 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007226 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007227 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007228
7229 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007230 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7231 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007232 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007233 struct mgmt_rp_read_local_oob_data rp;
7234 size_t rp_size = sizeof(rp);
7235
7236 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7237 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7238
Johan Hedberg710f11c2014-05-26 11:21:22 +03007239 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007240 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007241 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007242 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007243 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007244 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007245
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007246 mgmt_cmd_complete(cmd->sk, hdev->id,
7247 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7248 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007249 }
7250
7251 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007252}
Johan Hedberge17acd42011-03-30 23:57:16 +03007253
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007254static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7255{
7256 int i;
7257
7258 for (i = 0; i < uuid_count; i++) {
7259 if (!memcmp(uuid, uuids[i], 16))
7260 return true;
7261 }
7262
7263 return false;
7264}
7265
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007266static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7267{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007268 u16 parsed = 0;
7269
7270 while (parsed < eir_len) {
7271 u8 field_len = eir[0];
7272 u8 uuid[16];
7273 int i;
7274
7275 if (field_len == 0)
7276 break;
7277
7278 if (eir_len - parsed < field_len + 1)
7279 break;
7280
7281 switch (eir[1]) {
7282 case EIR_UUID16_ALL:
7283 case EIR_UUID16_SOME:
7284 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007285 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007286 uuid[13] = eir[i + 3];
7287 uuid[12] = eir[i + 2];
7288 if (has_uuid(uuid, uuid_count, uuids))
7289 return true;
7290 }
7291 break;
7292 case EIR_UUID32_ALL:
7293 case EIR_UUID32_SOME:
7294 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007295 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007296 uuid[15] = eir[i + 5];
7297 uuid[14] = eir[i + 4];
7298 uuid[13] = eir[i + 3];
7299 uuid[12] = eir[i + 2];
7300 if (has_uuid(uuid, uuid_count, uuids))
7301 return true;
7302 }
7303 break;
7304 case EIR_UUID128_ALL:
7305 case EIR_UUID128_SOME:
7306 for (i = 0; i + 17 <= field_len; i += 16) {
7307 memcpy(uuid, eir + i + 2, 16);
7308 if (has_uuid(uuid, uuid_count, uuids))
7309 return true;
7310 }
7311 break;
7312 }
7313
7314 parsed += field_len + 1;
7315 eir += field_len + 1;
7316 }
7317
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007318 return false;
7319}
7320
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007321static void restart_le_scan(struct hci_dev *hdev)
7322{
7323 /* If controller is not scanning we are done. */
7324 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7325 return;
7326
7327 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7328 hdev->discovery.scan_start +
7329 hdev->discovery.scan_duration))
7330 return;
7331
7332 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7333 DISCOV_LE_RESTART_DELAY);
7334}
7335
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007336static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7337 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7338{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007339 /* If a RSSI threshold has been specified, and
7340 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7341 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7342 * is set, let it through for further processing, as we might need to
7343 * restart the scan.
7344 *
7345 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7346 * the results are also dropped.
7347 */
7348 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7349 (rssi == HCI_RSSI_INVALID ||
7350 (rssi < hdev->discovery.rssi &&
7351 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7352 return false;
7353
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007354 if (hdev->discovery.uuid_count != 0) {
7355 /* If a list of UUIDs is provided in filter, results with no
7356 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007357 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007358 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7359 hdev->discovery.uuids) &&
7360 !eir_has_uuids(scan_rsp, scan_rsp_len,
7361 hdev->discovery.uuid_count,
7362 hdev->discovery.uuids))
7363 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007364 }
7365
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007366 /* If duplicate filtering does not report RSSI changes, then restart
7367 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007368 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007369 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7370 restart_le_scan(hdev);
7371
7372 /* Validate RSSI value against the RSSI threshold once more. */
7373 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7374 rssi < hdev->discovery.rssi)
7375 return false;
7376 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007377
7378 return true;
7379}
7380
Marcel Holtmann901801b2013-10-06 23:55:51 -07007381void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007382 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7383 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007384{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007385 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007386 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007387 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007388
Johan Hedberg75ce2082014-07-02 22:42:01 +03007389 /* Don't send events for a non-kernel initiated discovery. With
7390 * LE one exception is if we have pend_le_reports > 0 in which
7391 * case we're doing passive scanning and want these events.
7392 */
7393 if (!hci_discovery_active(hdev)) {
7394 if (link_type == ACL_LINK)
7395 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007396 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007397 return;
7398 }
Andre Guedes12602d02013-04-30 15:29:40 -03007399
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007400 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007401 /* We are using service discovery */
7402 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7403 scan_rsp_len))
7404 return;
7405 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007406
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007407 /* Make sure that the buffer is big enough. The 5 extra bytes
7408 * are for the potential CoD field.
7409 */
7410 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007411 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007412
Johan Hedberg1dc06092012-01-15 21:01:23 +02007413 memset(buf, 0, sizeof(buf));
7414
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007415 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7416 * RSSI value was reported as 0 when not available. This behavior
7417 * is kept when using device discovery. This is required for full
7418 * backwards compatibility with the API.
7419 *
7420 * However when using service discovery, the value 127 will be
7421 * returned when the RSSI is not available.
7422 */
Szymon Janc91200e92015-01-22 16:57:05 +01007423 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7424 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007425 rssi = 0;
7426
Johan Hedberg841c5642014-07-07 12:45:54 +03007427 bacpy(&ev->addr.bdaddr, bdaddr);
7428 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007429 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007430 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007431
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007432 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007433 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007434 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007435
Johan Hedberg1dc06092012-01-15 21:01:23 +02007436 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7437 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007438 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007439
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007440 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007441 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007442 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007443
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007444 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7445 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007446
Marcel Holtmann901801b2013-10-06 23:55:51 -07007447 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007448}
Johan Hedberga88a9652011-03-30 13:18:12 +03007449
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007450void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7451 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007452{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007453 struct mgmt_ev_device_found *ev;
7454 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7455 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007456
Johan Hedbergb644ba32012-01-17 21:48:47 +02007457 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007458
Johan Hedbergb644ba32012-01-17 21:48:47 +02007459 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007460
Johan Hedbergb644ba32012-01-17 21:48:47 +02007461 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007462 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007463 ev->rssi = rssi;
7464
7465 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007466 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007467
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007468 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007469
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007470 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007471}
Johan Hedberg314b2382011-04-27 10:29:57 -04007472
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007473void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007474{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007475 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007476
Andre Guedes343fb142011-11-22 17:14:19 -03007477 BT_DBG("%s discovering %u", hdev->name, discovering);
7478
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007479 memset(&ev, 0, sizeof(ev));
7480 ev.type = hdev->discovery.type;
7481 ev.discovering = discovering;
7482
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007483 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007484}
Antti Julku5e762442011-08-25 16:48:02 +03007485
Marcel Holtmann1904a852015-01-11 13:50:44 -08007486static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007487{
7488 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007489}
7490
7491void mgmt_reenable_advertising(struct hci_dev *hdev)
7492{
7493 struct hci_request req;
7494
Marcel Holtmann5976e602013-10-06 04:08:14 -07007495 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7496 return;
7497
7498 hci_req_init(&req, hdev);
7499 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007500 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007501}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007502
7503static struct hci_mgmt_chan chan = {
7504 .channel = HCI_CHANNEL_CONTROL,
7505 .handler_count = ARRAY_SIZE(mgmt_handlers),
7506 .handlers = mgmt_handlers,
7507};
7508
7509int mgmt_init(void)
7510{
7511 return hci_mgmt_chan_register(&chan);
7512}
7513
7514void mgmt_exit(void)
7515{
7516 hci_mgmt_chan_unregister(&chan);
7517}