blob: 6f20b78e1965a9b0a0427942cf0f49cd4433b08c [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 Hedbergeec8d2b2010-12-16 10:17:38 +0200138struct pending_cmd {
139 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 Hedberg9df74652014-12-19 22:26:03 +0200146 int (*cmd_complete)(struct 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
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200222static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
223 struct sock *skip_sk)
224{
225 struct sk_buff *skb;
226 struct mgmt_hdr *hdr;
227
228 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
229 if (!skb)
230 return -ENOMEM;
231
232 hdr = (void *) skb_put(skb, sizeof(*hdr));
233 hdr->opcode = cpu_to_le16(event);
234 if (hdev)
235 hdr->index = cpu_to_le16(hdev->id);
236 else
237 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
238 hdr->len = cpu_to_le16(data_len);
239
240 if (data)
241 memcpy(skb_put(skb, data_len), data, data_len);
242
243 /* Time stamp */
244 __net_timestamp(skb);
245
Johan Hedberg71290692015-02-20 13:26:23 +0200246 hci_send_to_channel(HCI_CHANNEL_CONTROL, skb, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200247 kfree_skb(skb);
248
249 return 0;
250}
251
Johan Hedberga69e8372015-03-06 21:08:53 +0200252static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253{
254 struct sk_buff *skb;
255 struct mgmt_hdr *hdr;
256 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300257 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200258
Szymon Janc34eb5252011-02-28 14:10:08 +0100259 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200260
Andre Guedes790eff42012-06-07 19:05:46 -0300261 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200262 if (!skb)
263 return -ENOMEM;
264
265 hdr = (void *) skb_put(skb, sizeof(*hdr));
266
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700267 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100268 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269 hdr->len = cpu_to_le16(sizeof(*ev));
270
271 ev = (void *) skb_put(skb, sizeof(*ev));
272 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200273 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200274
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300275 err = sock_queue_rcv_skb(sk, skb);
276 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200277 kfree_skb(skb);
278
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300279 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200280}
281
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200282static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300283 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200284{
285 struct sk_buff *skb;
286 struct mgmt_hdr *hdr;
287 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300288 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200289
290 BT_DBG("sock %p", sk);
291
Andre Guedes790eff42012-06-07 19:05:46 -0300292 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200293 if (!skb)
294 return -ENOMEM;
295
296 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200297
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700298 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100299 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200300 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200301
Johan Hedberga38528f2011-01-22 06:46:43 +0200302 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200303 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200304 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100305
306 if (rp)
307 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200308
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300309 err = sock_queue_rcv_skb(sk, skb);
310 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200311 kfree_skb(skb);
312
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100313 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200314}
315
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300316static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
317 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200318{
319 struct mgmt_rp_read_version rp;
320
321 BT_DBG("sock %p", sk);
322
323 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700324 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200325
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200326 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300327 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200328}
329
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300330static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
331 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332{
333 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200334 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
335 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200336 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200337 size_t rp_size;
338 int i, err;
339
340 BT_DBG("sock %p", sk);
341
342 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
343
344 rp = kmalloc(rp_size, GFP_KERNEL);
345 if (!rp)
346 return -ENOMEM;
347
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700348 rp->num_commands = cpu_to_le16(num_commands);
349 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200350
351 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
352 put_unaligned_le16(mgmt_commands[i], opcode);
353
354 for (i = 0; i < num_events; i++, opcode++)
355 put_unaligned_le16(mgmt_events[i], opcode);
356
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200357 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300358 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200359 kfree(rp);
360
361 return err;
362}
363
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300364static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
365 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200368 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200369 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300371 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200372
373 BT_DBG("sock %p", sk);
374
375 read_lock(&hci_dev_list_lock);
376
377 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300378 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200379 if (d->dev_type == HCI_BREDR &&
380 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700381 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 }
383
Johan Hedberga38528f2011-01-22 06:46:43 +0200384 rp_len = sizeof(*rp) + (2 * count);
385 rp = kmalloc(rp_len, GFP_ATOMIC);
386 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100387 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200388 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100389 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200390
Johan Hedberg476e44c2012-10-19 20:10:46 +0300391 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200392 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200394 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200395 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200396 continue;
397
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200398 /* Devices marked as raw-only are neither configured
399 * nor unconfigured controllers.
400 */
401 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700402 continue;
403
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200404 if (d->dev_type == HCI_BREDR &&
405 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700406 rp->index[count++] = cpu_to_le16(d->id);
407 BT_DBG("Added hci%u", d->id);
408 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 }
410
Johan Hedberg476e44c2012-10-19 20:10:46 +0300411 rp->num_controllers = cpu_to_le16(count);
412 rp_len = sizeof(*rp) + (2 * count);
413
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200414 read_unlock(&hci_dev_list_lock);
415
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200416 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300417 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200418
Johan Hedberga38528f2011-01-22 06:46:43 +0200419 kfree(rp);
420
421 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200422}
423
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200424static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
425 void *data, u16 data_len)
426{
427 struct mgmt_rp_read_unconf_index_list *rp;
428 struct hci_dev *d;
429 size_t rp_len;
430 u16 count;
431 int err;
432
433 BT_DBG("sock %p", sk);
434
435 read_lock(&hci_dev_list_lock);
436
437 count = 0;
438 list_for_each_entry(d, &hci_dev_list, list) {
439 if (d->dev_type == HCI_BREDR &&
440 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
441 count++;
442 }
443
444 rp_len = sizeof(*rp) + (2 * count);
445 rp = kmalloc(rp_len, GFP_ATOMIC);
446 if (!rp) {
447 read_unlock(&hci_dev_list_lock);
448 return -ENOMEM;
449 }
450
451 count = 0;
452 list_for_each_entry(d, &hci_dev_list, list) {
453 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200454 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200455 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
456 continue;
457
458 /* Devices marked as raw-only are neither configured
459 * nor unconfigured controllers.
460 */
461 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
462 continue;
463
464 if (d->dev_type == HCI_BREDR &&
465 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
466 rp->index[count++] = cpu_to_le16(d->id);
467 BT_DBG("Added hci%u", d->id);
468 }
469 }
470
471 rp->num_controllers = cpu_to_le16(count);
472 rp_len = sizeof(*rp) + (2 * count);
473
474 read_unlock(&hci_dev_list_lock);
475
476 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
477 0, rp, rp_len);
478
479 kfree(rp);
480
481 return err;
482}
483
Marcel Holtmanndbece372014-07-04 18:11:55 +0200484static bool is_configured(struct hci_dev *hdev)
485{
486 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
487 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
488 return false;
489
490 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
491 !bacmp(&hdev->public_addr, BDADDR_ANY))
492 return false;
493
494 return true;
495}
496
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200497static __le32 get_missing_options(struct hci_dev *hdev)
498{
499 u32 options = 0;
500
Marcel Holtmanndbece372014-07-04 18:11:55 +0200501 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
502 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200503 options |= MGMT_OPTION_EXTERNAL_CONFIG;
504
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200505 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
506 !bacmp(&hdev->public_addr, BDADDR_ANY))
507 options |= MGMT_OPTION_PUBLIC_ADDRESS;
508
509 return cpu_to_le32(options);
510}
511
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200512static int new_options(struct hci_dev *hdev, struct sock *skip)
513{
514 __le32 options = get_missing_options(hdev);
515
516 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
517 sizeof(options), skip);
518}
519
Marcel Holtmanndbece372014-07-04 18:11:55 +0200520static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
521{
522 __le32 options = get_missing_options(hdev);
523
524 return cmd_complete(sk, hdev->id, opcode, 0, &options,
525 sizeof(options));
526}
527
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528static int read_config_info(struct sock *sk, struct hci_dev *hdev,
529 void *data, u16 data_len)
530{
531 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200532 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200533
534 BT_DBG("sock %p %s", sk, hdev->name);
535
536 hci_dev_lock(hdev);
537
538 memset(&rp, 0, sizeof(rp));
539 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200541 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
542 options |= MGMT_OPTION_EXTERNAL_CONFIG;
543
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200545 options |= MGMT_OPTION_PUBLIC_ADDRESS;
546
547 rp.supported_options = cpu_to_le32(options);
548 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200549
550 hci_dev_unlock(hdev);
551
552 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
553 sizeof(rp));
554}
555
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200557{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200558 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200559
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200560 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300561 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800562 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300563 settings |= MGMT_SETTING_CONNECTABLE;
564 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200565
Andre Guedesed3fa312012-07-24 15:03:46 -0300566 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500567 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
568 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200569 settings |= MGMT_SETTING_BREDR;
570 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700571
572 if (lmp_ssp_capable(hdev)) {
573 settings |= MGMT_SETTING_SSP;
574 settings |= MGMT_SETTING_HS;
575 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800576
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800577 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800578 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700579 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100580
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200582 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300583 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300584 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200585 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800586 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300587 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200588
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200589 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
590 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200591 settings |= MGMT_SETTING_CONFIGURATION;
592
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200593 return settings;
594}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200595
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200596static u32 get_current_settings(struct hci_dev *hdev)
597{
598 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200599
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200600 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100601 settings |= MGMT_SETTING_POWERED;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_CONNECTABLE;
605
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500606 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
607 settings |= MGMT_SETTING_FAST_CONNECTABLE;
608
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200609 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_DISCOVERABLE;
611
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300612 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300613 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614
Johan Hedberg56f87902013-10-02 13:43:13 +0300615 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_BREDR;
617
Johan Hedberg06199cf2012-02-22 16:37:11 +0200618 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200620
Johan Hedberg47990ea2012-02-22 11:58:37 +0200621 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200622 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200623
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200624 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200625 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200626
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200627 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_HS;
629
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200630 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300631 settings |= MGMT_SETTING_ADVERTISING;
632
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800633 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
634 settings |= MGMT_SETTING_SECURE_CONN;
635
Johan Hedberg0663b292014-06-24 13:15:50 +0300636 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800637 settings |= MGMT_SETTING_DEBUG_KEYS;
638
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200639 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
640 settings |= MGMT_SETTING_PRIVACY;
641
Marcel Holtmann93690c22015-03-06 10:11:21 -0800642 /* The current setting for static address has two purposes. The
643 * first is to indicate if the static address will be used and
644 * the second is to indicate if it is actually set.
645 *
646 * This means if the static address is not configured, this flag
647 * will never bet set. If the address is configured, then if the
648 * address is actually used decides if the flag is set or not.
649 *
650 * For single mode LE only controllers and dual-mode controllers
651 * with BR/EDR disabled, the existence of the static address will
652 * be evaluated.
653 */
654 if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ||
655 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
656 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
657 if (bacmp(&hdev->static_addr, BDADDR_ANY))
658 settings |= MGMT_SETTING_STATIC_ADDRESS;
659 }
660
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200661 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200662}
663
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300664#define PNP_INFO_SVCLASS_ID 0x1200
665
Johan Hedberg213202e2013-01-27 00:31:33 +0200666static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
667{
668 u8 *ptr = data, *uuids_start = NULL;
669 struct bt_uuid *uuid;
670
671 if (len < 4)
672 return ptr;
673
674 list_for_each_entry(uuid, &hdev->uuids, list) {
675 u16 uuid16;
676
677 if (uuid->size != 16)
678 continue;
679
680 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
681 if (uuid16 < 0x1100)
682 continue;
683
684 if (uuid16 == PNP_INFO_SVCLASS_ID)
685 continue;
686
687 if (!uuids_start) {
688 uuids_start = ptr;
689 uuids_start[0] = 1;
690 uuids_start[1] = EIR_UUID16_ALL;
691 ptr += 2;
692 }
693
694 /* Stop if not enough space to put next UUID */
695 if ((ptr - data) + sizeof(u16) > len) {
696 uuids_start[1] = EIR_UUID16_SOME;
697 break;
698 }
699
700 *ptr++ = (uuid16 & 0x00ff);
701 *ptr++ = (uuid16 & 0xff00) >> 8;
702 uuids_start[0] += sizeof(uuid16);
703 }
704
705 return ptr;
706}
707
Johan Hedbergcdf19632013-01-27 00:31:34 +0200708static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
709{
710 u8 *ptr = data, *uuids_start = NULL;
711 struct bt_uuid *uuid;
712
713 if (len < 6)
714 return ptr;
715
716 list_for_each_entry(uuid, &hdev->uuids, list) {
717 if (uuid->size != 32)
718 continue;
719
720 if (!uuids_start) {
721 uuids_start = ptr;
722 uuids_start[0] = 1;
723 uuids_start[1] = EIR_UUID32_ALL;
724 ptr += 2;
725 }
726
727 /* Stop if not enough space to put next UUID */
728 if ((ptr - data) + sizeof(u32) > len) {
729 uuids_start[1] = EIR_UUID32_SOME;
730 break;
731 }
732
733 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
734 ptr += sizeof(u32);
735 uuids_start[0] += sizeof(u32);
736 }
737
738 return ptr;
739}
740
Johan Hedbergc00d5752013-01-27 00:31:35 +0200741static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
742{
743 u8 *ptr = data, *uuids_start = NULL;
744 struct bt_uuid *uuid;
745
746 if (len < 18)
747 return ptr;
748
749 list_for_each_entry(uuid, &hdev->uuids, list) {
750 if (uuid->size != 128)
751 continue;
752
753 if (!uuids_start) {
754 uuids_start = ptr;
755 uuids_start[0] = 1;
756 uuids_start[1] = EIR_UUID128_ALL;
757 ptr += 2;
758 }
759
760 /* Stop if not enough space to put next UUID */
761 if ((ptr - data) + 16 > len) {
762 uuids_start[1] = EIR_UUID128_SOME;
763 break;
764 }
765
766 memcpy(ptr, uuid->uuid, 16);
767 ptr += 16;
768 uuids_start[0] += 16;
769 }
770
771 return ptr;
772}
773
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300774static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
775{
776 struct pending_cmd *cmd;
777
778 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
779 if (cmd->opcode == opcode)
780 return cmd;
781 }
782
783 return NULL;
784}
785
Johan Hedberg95868422014-06-28 17:54:07 +0300786static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
787 struct hci_dev *hdev,
788 const void *data)
789{
790 struct pending_cmd *cmd;
791
792 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
793 if (cmd->user_data != data)
794 continue;
795 if (cmd->opcode == opcode)
796 return cmd;
797 }
798
799 return NULL;
800}
801
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700802static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
803{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700804 u8 ad_len = 0;
805 size_t name_len;
806
807 name_len = strlen(hdev->dev_name);
808 if (name_len > 0) {
809 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
810
811 if (name_len > max_len) {
812 name_len = max_len;
813 ptr[1] = EIR_NAME_SHORT;
814 } else
815 ptr[1] = EIR_NAME_COMPLETE;
816
817 ptr[0] = name_len + 1;
818
819 memcpy(ptr + 2, hdev->dev_name, name_len);
820
821 ad_len += (name_len + 2);
822 ptr += (name_len + 2);
823 }
824
825 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700826}
827
828static void update_scan_rsp_data(struct hci_request *req)
829{
830 struct hci_dev *hdev = req->hdev;
831 struct hci_cp_le_set_scan_rsp_data cp;
832 u8 len;
833
Johan Hedberg7751ef12013-10-19 23:38:15 +0300834 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700835 return;
836
837 memset(&cp, 0, sizeof(cp));
838
839 len = create_scan_rsp_data(hdev, cp.data);
840
Johan Hedbergeb438b52013-10-16 15:31:07 +0300841 if (hdev->scan_rsp_data_len == len &&
842 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700843 return;
844
Johan Hedbergeb438b52013-10-16 15:31:07 +0300845 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
846 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700847
848 cp.length = len;
849
850 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
851}
852
Johan Hedberg9a43e252013-10-20 19:00:07 +0300853static u8 get_adv_discov_flags(struct hci_dev *hdev)
854{
855 struct pending_cmd *cmd;
856
857 /* If there's a pending mgmt command the flags will not yet have
858 * their final values, so check for this first.
859 */
860 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
861 if (cmd) {
862 struct mgmt_mode *cp = cmd->param;
863 if (cp->val == 0x01)
864 return LE_AD_GENERAL;
865 else if (cp->val == 0x02)
866 return LE_AD_LIMITED;
867 } else {
868 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
869 return LE_AD_LIMITED;
870 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
871 return LE_AD_GENERAL;
872 }
873
874 return 0;
875}
876
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700877static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700878{
879 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700880
Johan Hedberg9a43e252013-10-20 19:00:07 +0300881 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882
Johan Hedberge8340042014-01-30 11:16:50 -0800883 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700884 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885
886 if (flags) {
887 BT_DBG("adv flags 0x%02x", flags);
888
889 ptr[0] = 2;
890 ptr[1] = EIR_FLAGS;
891 ptr[2] = flags;
892
893 ad_len += 3;
894 ptr += 3;
895 }
896
897 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
898 ptr[0] = 2;
899 ptr[1] = EIR_TX_POWER;
900 ptr[2] = (u8) hdev->adv_tx_power;
901
902 ad_len += 3;
903 ptr += 3;
904 }
905
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700906 return ad_len;
907}
908
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700909static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700910{
911 struct hci_dev *hdev = req->hdev;
912 struct hci_cp_le_set_adv_data cp;
913 u8 len;
914
Johan Hedberg10994ce2013-10-19 23:38:16 +0300915 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700916 return;
917
918 memset(&cp, 0, sizeof(cp));
919
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700920 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700921
922 if (hdev->adv_data_len == len &&
923 memcmp(cp.data, hdev->adv_data, len) == 0)
924 return;
925
926 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
927 hdev->adv_data_len = len;
928
929 cp.length = len;
930
931 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
932}
933
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300934int mgmt_update_adv_data(struct hci_dev *hdev)
935{
936 struct hci_request req;
937
938 hci_req_init(&req, hdev);
939 update_adv_data(&req);
940
941 return hci_req_run(&req, NULL);
942}
943
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300944static void create_eir(struct hci_dev *hdev, u8 *data)
945{
946 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300947 size_t name_len;
948
949 name_len = strlen(hdev->dev_name);
950
951 if (name_len > 0) {
952 /* EIR Data type */
953 if (name_len > 48) {
954 name_len = 48;
955 ptr[1] = EIR_NAME_SHORT;
956 } else
957 ptr[1] = EIR_NAME_COMPLETE;
958
959 /* EIR Data length */
960 ptr[0] = name_len + 1;
961
962 memcpy(ptr + 2, hdev->dev_name, name_len);
963
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300964 ptr += (name_len + 2);
965 }
966
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100967 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700968 ptr[0] = 2;
969 ptr[1] = EIR_TX_POWER;
970 ptr[2] = (u8) hdev->inq_tx_power;
971
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700972 ptr += 3;
973 }
974
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700975 if (hdev->devid_source > 0) {
976 ptr[0] = 9;
977 ptr[1] = EIR_DEVICE_ID;
978
979 put_unaligned_le16(hdev->devid_source, ptr + 2);
980 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
981 put_unaligned_le16(hdev->devid_product, ptr + 6);
982 put_unaligned_le16(hdev->devid_version, ptr + 8);
983
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700984 ptr += 10;
985 }
986
Johan Hedberg213202e2013-01-27 00:31:33 +0200987 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200988 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200989 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300990}
991
Johan Hedberg890ea892013-03-15 17:06:52 -0500992static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300993{
Johan Hedberg890ea892013-03-15 17:06:52 -0500994 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300995 struct hci_cp_write_eir cp;
996
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200997 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500998 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200999
Johan Hedberg976eb202012-10-24 21:12:01 +03001000 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001001 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001002
Johan Hedberg84bde9d2012-01-25 14:21:06 +02001003 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001004 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001005
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001006 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001007 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001008
1009 memset(&cp, 0, sizeof(cp));
1010
1011 create_eir(hdev, cp.data);
1012
1013 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001014 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001015
1016 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1017
Johan Hedberg890ea892013-03-15 17:06:52 -05001018 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001019}
1020
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001021static u8 get_service_classes(struct hci_dev *hdev)
1022{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001023 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001024 u8 val = 0;
1025
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001026 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001027 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001028
1029 return val;
1030}
1031
Johan Hedberg890ea892013-03-15 17:06:52 -05001032static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033{
Johan Hedberg890ea892013-03-15 17:06:52 -05001034 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001035 u8 cod[3];
1036
1037 BT_DBG("%s", hdev->name);
1038
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001039 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001040 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001041
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001042 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1043 return;
1044
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001045 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001046 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001047
1048 cod[0] = hdev->minor_class;
1049 cod[1] = hdev->major_class;
1050 cod[2] = get_service_classes(hdev);
1051
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001052 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1053 cod[1] |= 0x20;
1054
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001055 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001056 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001057
Johan Hedberg890ea892013-03-15 17:06:52 -05001058 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001059}
1060
Johan Hedberga4858cb2014-02-25 19:56:31 +02001061static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001062{
1063 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001064
1065 /* If there's a pending mgmt command the flag will not yet have
1066 * it's final value, so check for this first.
1067 */
1068 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1069 if (cmd) {
1070 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001071 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001072 }
1073
Johan Hedberga4858cb2014-02-25 19:56:31 +02001074 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001075}
1076
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001077static void disable_advertising(struct hci_request *req)
1078{
1079 u8 enable = 0x00;
1080
1081 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1082}
1083
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001084static void enable_advertising(struct hci_request *req)
1085{
1086 struct hci_dev *hdev = req->hdev;
1087 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001088 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001089 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001090
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001091 if (hci_conn_num(hdev, LE_LINK) > 0)
1092 return;
1093
1094 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1095 disable_advertising(req);
1096
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001097 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001098 * hci_update_random_address knows that it's safe to go ahead
1099 * and write a new random address. The flag will be set back on
1100 * as soon as the SET_ADV_ENABLE HCI command completes.
1101 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001102 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001103
Johan Hedberga4858cb2014-02-25 19:56:31 +02001104 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001105
Johan Hedberga4858cb2014-02-25 19:56:31 +02001106 /* Set require_privacy to true only when non-connectable
1107 * advertising is used. In that case it is fine to use a
1108 * non-resolvable private address.
1109 */
1110 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001111 return;
1112
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001113 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001114 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1115 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001116 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001117 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001118 cp.channel_map = hdev->le_adv_channel_map;
1119
1120 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1121
1122 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1123}
1124
Johan Hedberg7d785252011-12-15 00:47:39 +02001125static void service_cache_off(struct work_struct *work)
1126{
1127 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001128 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001129 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001130
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001131 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001132 return;
1133
Johan Hedberg890ea892013-03-15 17:06:52 -05001134 hci_req_init(&req, hdev);
1135
Johan Hedberg7d785252011-12-15 00:47:39 +02001136 hci_dev_lock(hdev);
1137
Johan Hedberg890ea892013-03-15 17:06:52 -05001138 update_eir(&req);
1139 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001140
1141 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001142
1143 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001144}
1145
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001146static void rpa_expired(struct work_struct *work)
1147{
1148 struct hci_dev *hdev = container_of(work, struct hci_dev,
1149 rpa_expired.work);
1150 struct hci_request req;
1151
1152 BT_DBG("");
1153
1154 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1155
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001156 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001157 return;
1158
1159 /* The generation of a new RPA and programming it into the
1160 * controller happens in the enable_advertising() function.
1161 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001162 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001163 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001164 hci_req_run(&req, NULL);
1165}
1166
Johan Hedberg6a919082012-02-28 06:17:26 +02001167static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001168{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001169 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001170 return;
1171
Johan Hedberg4f87da82012-03-02 19:55:56 +02001172 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001173 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001174
Johan Hedberg4f87da82012-03-02 19:55:56 +02001175 /* Non-mgmt controlled devices get this bit set
1176 * implicitly so that pairing works for them, however
1177 * for mgmt we require user-space to explicitly enable
1178 * it
1179 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001180 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001181}
1182
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001183static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001184 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001185{
1186 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001188 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001189
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001190 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001191
Johan Hedberg03811012010-12-08 00:21:06 +02001192 memset(&rp, 0, sizeof(rp));
1193
Johan Hedberg03811012010-12-08 00:21:06 +02001194 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001195
1196 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001197 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001198
1199 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1200 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1201
1202 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001203
1204 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001205 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001206
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001207 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001208
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001209 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001210 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001211}
1212
1213static void mgmt_pending_free(struct pending_cmd *cmd)
1214{
1215 sock_put(cmd->sk);
1216 kfree(cmd->param);
1217 kfree(cmd);
1218}
1219
1220static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001221 struct hci_dev *hdev, void *data,
1222 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001223{
1224 struct pending_cmd *cmd;
1225
Johan Hedbergfca20012014-06-28 17:54:05 +03001226 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001227 if (!cmd)
1228 return NULL;
1229
1230 cmd->opcode = opcode;
1231 cmd->index = hdev->id;
1232
Johan Hedberg323b0b82014-12-05 13:36:01 +02001233 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001234 if (!cmd->param) {
1235 kfree(cmd);
1236 return NULL;
1237 }
1238
Johan Hedberg323b0b82014-12-05 13:36:01 +02001239 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001240
1241 cmd->sk = sk;
1242 sock_hold(sk);
1243
1244 list_add(&cmd->list, &hdev->mgmt_pending);
1245
1246 return cmd;
1247}
1248
1249static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001250 void (*cb)(struct pending_cmd *cmd,
1251 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001252 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001253{
Andre Guedesa3d09352013-02-01 11:21:30 -03001254 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001255
Andre Guedesa3d09352013-02-01 11:21:30 -03001256 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001257 if (opcode > 0 && cmd->opcode != opcode)
1258 continue;
1259
1260 cb(cmd, data);
1261 }
1262}
1263
Johan Hedberg03811012010-12-08 00:21:06 +02001264static void mgmt_pending_remove(struct pending_cmd *cmd)
1265{
1266 list_del(&cmd->list);
1267 mgmt_pending_free(cmd);
1268}
1269
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001270static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001271{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001272 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001273
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001274 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001275 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001276}
1277
Marcel Holtmann1904a852015-01-11 13:50:44 -08001278static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001279{
1280 BT_DBG("%s status 0x%02x", hdev->name, status);
1281
Johan Hedberga3172b72014-02-28 09:33:44 +02001282 if (hci_conn_count(hdev) == 0) {
1283 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001284 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001285 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001286}
1287
Johan Hedberg23a48092014-07-08 16:05:06 +03001288static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001289{
1290 struct hci_dev *hdev = req->hdev;
1291 struct hci_cp_remote_name_req_cancel cp;
1292 struct inquiry_entry *e;
1293
1294 switch (hdev->discovery.state) {
1295 case DISCOVERY_FINDING:
1296 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1297 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1298 } else {
1299 cancel_delayed_work(&hdev->le_scan_disable);
1300 hci_req_add_le_scan_disable(req);
1301 }
1302
Johan Hedberg23a48092014-07-08 16:05:06 +03001303 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304
1305 case DISCOVERY_RESOLVING:
1306 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1307 NAME_PENDING);
1308 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001309 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001310
1311 bacpy(&cp.bdaddr, &e->data.bdaddr);
1312 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1313 &cp);
1314
Johan Hedberg23a48092014-07-08 16:05:06 +03001315 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001316
1317 default:
1318 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001319 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001320 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001321 return true;
1322 }
1323
Johan Hedberg21a60d32014-06-10 14:05:58 +03001324 break;
1325 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001326
1327 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001328}
1329
Johan Hedberg8b064a32014-02-24 14:52:22 +02001330static int clean_up_hci_state(struct hci_dev *hdev)
1331{
1332 struct hci_request req;
1333 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001334 bool discov_stopped;
1335 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001336
1337 hci_req_init(&req, hdev);
1338
1339 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1340 test_bit(HCI_PSCAN, &hdev->flags)) {
1341 u8 scan = 0x00;
1342 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1343 }
1344
Johan Hedberg73e082f2014-07-08 15:07:51 +03001345 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001346 disable_advertising(&req);
1347
Johan Hedberg23a48092014-07-08 16:05:06 +03001348 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001349
1350 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1351 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001352 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001353
Johan Hedbergc9910d02014-02-27 14:35:12 +02001354 switch (conn->state) {
1355 case BT_CONNECTED:
1356 case BT_CONFIG:
1357 dc.handle = cpu_to_le16(conn->handle);
1358 dc.reason = 0x15; /* Terminated due to Power Off */
1359 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1360 break;
1361 case BT_CONNECT:
1362 if (conn->type == LE_LINK)
1363 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1364 0, NULL);
1365 else if (conn->type == ACL_LINK)
1366 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1367 6, &conn->dst);
1368 break;
1369 case BT_CONNECT2:
1370 bacpy(&rej.bdaddr, &conn->dst);
1371 rej.reason = 0x15; /* Terminated due to Power Off */
1372 if (conn->type == ACL_LINK)
1373 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1374 sizeof(rej), &rej);
1375 else if (conn->type == SCO_LINK)
1376 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1377 sizeof(rej), &rej);
1378 break;
1379 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001380 }
1381
Johan Hedberg23a48092014-07-08 16:05:06 +03001382 err = hci_req_run(&req, clean_up_hci_complete);
1383 if (!err && discov_stopped)
1384 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1385
1386 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001387}
1388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001389static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001390 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001391{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001392 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001393 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001394 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001396 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001397
Johan Hedberga7e80f22013-01-09 16:05:19 +02001398 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001399 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1400 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001401
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001402 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001403
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001404 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001405 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1406 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001407 goto failed;
1408 }
1409
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001410 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1411 cancel_delayed_work(&hdev->power_off);
1412
1413 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001414 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1415 data, len);
1416 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001417 goto failed;
1418 }
1419 }
1420
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001421 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001422 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001423 goto failed;
1424 }
1425
Johan Hedberg03811012010-12-08 00:21:06 +02001426 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1427 if (!cmd) {
1428 err = -ENOMEM;
1429 goto failed;
1430 }
1431
Johan Hedberg8b064a32014-02-24 14:52:22 +02001432 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001433 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001434 err = 0;
1435 } else {
1436 /* Disconnect connections, stop scans, etc */
1437 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001438 if (!err)
1439 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1440 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001441
Johan Hedberg8b064a32014-02-24 14:52:22 +02001442 /* ENODATA means there were no HCI commands queued */
1443 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001444 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001445 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1446 err = 0;
1447 }
1448 }
Johan Hedberg03811012010-12-08 00:21:06 +02001449
1450failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001451 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001452 return err;
1453}
1454
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001455static int new_settings(struct hci_dev *hdev, struct sock *skip)
1456{
1457 __le32 ev;
1458
1459 ev = cpu_to_le32(get_current_settings(hdev));
1460
1461 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1462}
1463
Johan Hedberg91a668b2014-07-09 13:28:26 +03001464int mgmt_new_settings(struct hci_dev *hdev)
1465{
1466 return new_settings(hdev, NULL);
1467}
1468
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001469struct cmd_lookup {
1470 struct sock *sk;
1471 struct hci_dev *hdev;
1472 u8 mgmt_status;
1473};
1474
1475static void settings_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 struct cmd_lookup *match = data;
1478
1479 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1480
1481 list_del(&cmd->list);
1482
1483 if (match->sk == NULL) {
1484 match->sk = cmd->sk;
1485 sock_hold(match->sk);
1486 }
1487
1488 mgmt_pending_free(cmd);
1489}
1490
1491static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1492{
1493 u8 *status = data;
1494
Johan Hedberga69e8372015-03-06 21:08:53 +02001495 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001496 mgmt_pending_remove(cmd);
1497}
1498
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001499static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1500{
1501 if (cmd->cmd_complete) {
1502 u8 *status = data;
1503
1504 cmd->cmd_complete(cmd, *status);
1505 mgmt_pending_remove(cmd);
1506
1507 return;
1508 }
1509
1510 cmd_status_rsp(cmd, data);
1511}
1512
Johan Hedberg9df74652014-12-19 22:26:03 +02001513static int generic_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001514{
Johan Hedberg9df74652014-12-19 22:26:03 +02001515 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1516 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001517}
1518
Johan Hedberg9df74652014-12-19 22:26:03 +02001519static int addr_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001520{
Johan Hedberg9df74652014-12-19 22:26:03 +02001521 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1522 sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001523}
1524
Johan Hedberge6fe7982013-10-02 15:45:22 +03001525static u8 mgmt_bredr_support(struct hci_dev *hdev)
1526{
1527 if (!lmp_bredr_capable(hdev))
1528 return MGMT_STATUS_NOT_SUPPORTED;
1529 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1530 return MGMT_STATUS_REJECTED;
1531 else
1532 return MGMT_STATUS_SUCCESS;
1533}
1534
1535static u8 mgmt_le_support(struct hci_dev *hdev)
1536{
1537 if (!lmp_le_capable(hdev))
1538 return MGMT_STATUS_NOT_SUPPORTED;
1539 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1540 return MGMT_STATUS_REJECTED;
1541 else
1542 return MGMT_STATUS_SUCCESS;
1543}
1544
Marcel Holtmann1904a852015-01-11 13:50:44 -08001545static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1546 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001547{
1548 struct pending_cmd *cmd;
1549 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001550 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001551 bool changed;
1552
1553 BT_DBG("status 0x%02x", status);
1554
1555 hci_dev_lock(hdev);
1556
1557 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1558 if (!cmd)
1559 goto unlock;
1560
1561 if (status) {
1562 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001563 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001564 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001565 goto remove_cmd;
1566 }
1567
1568 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001569 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001570 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1571 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001572
1573 if (hdev->discov_timeout > 0) {
1574 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1575 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1576 to);
1577 }
1578 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001579 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1580 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001581 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001582
1583 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1584
1585 if (changed)
1586 new_settings(hdev, cmd->sk);
1587
Marcel Holtmann970ba522013-10-15 06:33:57 -07001588 /* When the discoverable mode gets changed, make sure
1589 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001590 * bit correctly set. Also update page scan based on whitelist
1591 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001592 */
1593 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001594 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001595 update_class(&req);
1596 hci_req_run(&req, NULL);
1597
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001598remove_cmd:
1599 mgmt_pending_remove(cmd);
1600
1601unlock:
1602 hci_dev_unlock(hdev);
1603}
1604
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001605static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001606 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001607{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001608 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001609 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001610 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001611 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001612 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001613 int err;
1614
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001615 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001616
Johan Hedberg9a43e252013-10-20 19:00:07 +03001617 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1618 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02001619 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1620 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001621
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001622 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001623 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1624 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001625
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001626 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001627
1628 /* Disabling discoverable requires that no timeout is set,
1629 * and enabling limited discoverable requires a timeout.
1630 */
1631 if ((cp->val == 0x00 && timeout > 0) ||
1632 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001633 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1634 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001635
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001636 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001637
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001638 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001639 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1640 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001641 goto failed;
1642 }
1643
1644 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001645 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001646 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1647 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001648 goto failed;
1649 }
1650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001651 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001652 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1653 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001654 goto failed;
1655 }
1656
1657 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001658 bool changed = false;
1659
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001660 /* Setting limited discoverable when powered off is
1661 * not a valid operation since it requires a timeout
1662 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1663 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001664 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1665 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1666 changed = true;
1667 }
1668
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001669 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001670 if (err < 0)
1671 goto failed;
1672
1673 if (changed)
1674 err = new_settings(hdev, sk);
1675
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001676 goto failed;
1677 }
1678
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001679 /* If the current mode is the same, then just update the timeout
1680 * value with the new value. And if only the timeout gets updated,
1681 * then no need for any HCI transactions.
1682 */
1683 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1684 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1685 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001686 cancel_delayed_work(&hdev->discov_off);
1687 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001688
Marcel Holtmann36261542013-10-15 08:28:51 -07001689 if (cp->val && hdev->discov_timeout > 0) {
1690 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001691 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001692 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001693 }
1694
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001695 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001696 goto failed;
1697 }
1698
1699 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1700 if (!cmd) {
1701 err = -ENOMEM;
1702 goto failed;
1703 }
1704
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001705 /* Cancel any potential discoverable timeout that might be
1706 * still active and store new timeout value. The arming of
1707 * the timeout happens in the complete handler.
1708 */
1709 cancel_delayed_work(&hdev->discov_off);
1710 hdev->discov_timeout = timeout;
1711
Johan Hedbergb456f872013-10-19 23:38:22 +03001712 /* Limited discoverable mode */
1713 if (cp->val == 0x02)
1714 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1715 else
1716 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1717
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001718 hci_req_init(&req, hdev);
1719
Johan Hedberg9a43e252013-10-20 19:00:07 +03001720 /* The procedure for LE-only controllers is much simpler - just
1721 * update the advertising data.
1722 */
1723 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1724 goto update_ad;
1725
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001726 scan = SCAN_PAGE;
1727
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001728 if (cp->val) {
1729 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001730
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001731 if (cp->val == 0x02) {
1732 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001733 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001734 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1735 hci_cp.iac_lap[1] = 0x8b;
1736 hci_cp.iac_lap[2] = 0x9e;
1737 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1738 hci_cp.iac_lap[4] = 0x8b;
1739 hci_cp.iac_lap[5] = 0x9e;
1740 } else {
1741 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001742 hci_cp.num_iac = 1;
1743 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1744 hci_cp.iac_lap[1] = 0x8b;
1745 hci_cp.iac_lap[2] = 0x9e;
1746 }
1747
1748 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1749 (hci_cp.num_iac * 3) + 1, &hci_cp);
1750
1751 scan |= SCAN_INQUIRY;
1752 } else {
1753 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1754 }
1755
1756 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001757
Johan Hedberg9a43e252013-10-20 19:00:07 +03001758update_ad:
1759 update_adv_data(&req);
1760
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001761 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001762 if (err < 0)
1763 mgmt_pending_remove(cmd);
1764
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001765failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001766 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001767 return err;
1768}
1769
Johan Hedberg406d7802013-03-15 17:07:09 -05001770static void write_fast_connectable(struct hci_request *req, bool enable)
1771{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001772 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001773 struct hci_cp_write_page_scan_activity acp;
1774 u8 type;
1775
Johan Hedberg547003b2013-10-21 16:51:53 +03001776 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1777 return;
1778
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001779 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1780 return;
1781
Johan Hedberg406d7802013-03-15 17:07:09 -05001782 if (enable) {
1783 type = PAGE_SCAN_TYPE_INTERLACED;
1784
1785 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001786 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001787 } else {
1788 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1789
1790 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001791 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001792 }
1793
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001794 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001795
Johan Hedbergbd98b992013-03-15 17:07:13 -05001796 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1797 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1798 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1799 sizeof(acp), &acp);
1800
1801 if (hdev->page_scan_type != type)
1802 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001803}
1804
Marcel Holtmann1904a852015-01-11 13:50:44 -08001805static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1806 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001807{
1808 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001809 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001810 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001811
1812 BT_DBG("status 0x%02x", status);
1813
1814 hci_dev_lock(hdev);
1815
1816 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1817 if (!cmd)
1818 goto unlock;
1819
Johan Hedberg37438c12013-10-14 16:20:05 +03001820 if (status) {
1821 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001822 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001823 goto remove_cmd;
1824 }
1825
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001826 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001827 if (cp->val) {
1828 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1829 &hdev->dev_flags);
1830 discov_changed = false;
1831 } else {
1832 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1833 &hdev->dev_flags);
1834 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1835 &hdev->dev_flags);
1836 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001837
Johan Hedberg2b76f452013-03-15 17:07:04 -05001838 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1839
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001840 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001841 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001842 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001843 if (discov_changed)
1844 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001845 hci_update_background_scan(hdev);
1846 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001847
Johan Hedberg37438c12013-10-14 16:20:05 +03001848remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001849 mgmt_pending_remove(cmd);
1850
1851unlock:
1852 hci_dev_unlock(hdev);
1853}
1854
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001855static int set_connectable_update_settings(struct hci_dev *hdev,
1856 struct sock *sk, u8 val)
1857{
1858 bool changed = false;
1859 int err;
1860
1861 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1862 changed = true;
1863
1864 if (val) {
1865 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1866 } else {
1867 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1868 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1869 }
1870
1871 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1872 if (err < 0)
1873 return err;
1874
Johan Hedberg562064e2014-07-08 16:35:34 +03001875 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001876 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001877 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001878 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001879 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001880
1881 return 0;
1882}
1883
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001884static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001885 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001886{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001887 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001888 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001889 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001890 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001891 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001892
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001893 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001894
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001895 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1896 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02001897 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1898 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001899
Johan Hedberga7e80f22013-01-09 16:05:19 +02001900 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001901 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1902 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001903
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001904 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001905
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001906 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001907 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001908 goto failed;
1909 }
1910
1911 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001912 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001913 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1914 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001915 goto failed;
1916 }
1917
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001918 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1919 if (!cmd) {
1920 err = -ENOMEM;
1921 goto failed;
1922 }
1923
Johan Hedberg2b76f452013-03-15 17:07:04 -05001924 hci_req_init(&req, hdev);
1925
Johan Hedberg9a43e252013-10-20 19:00:07 +03001926 /* If BR/EDR is not enabled and we disable advertising as a
1927 * by-product of disabling connectable, we need to update the
1928 * advertising flags.
1929 */
1930 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1931 if (!cp->val) {
1932 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1933 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1934 }
1935 update_adv_data(&req);
1936 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001937 if (cp->val) {
1938 scan = SCAN_PAGE;
1939 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001940 /* If we don't have any whitelist entries just
1941 * disable all scanning. If there are entries
1942 * and we had both page and inquiry scanning
1943 * enabled then fall back to only page scanning.
1944 * Otherwise no changes are needed.
1945 */
1946 if (list_empty(&hdev->whitelist))
1947 scan = SCAN_DISABLED;
1948 else if (test_bit(HCI_ISCAN, &hdev->flags))
1949 scan = SCAN_PAGE;
1950 else
1951 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001952
1953 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001954 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 cancel_delayed_work(&hdev->discov_off);
1956 }
1957
1958 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1959 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001960
Johan Hedberg3bd27242014-07-28 20:53:58 +03001961no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001962 /* If we're going from non-connectable to connectable or
1963 * vice-versa when fast connectable is enabled ensure that fast
1964 * connectable gets disabled. write_fast_connectable won't do
1965 * anything if the page scan parameters are already what they
1966 * should be.
1967 */
1968 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001969 write_fast_connectable(&req, false);
1970
Johan Hedberge8b12022014-07-10 10:51:27 +03001971 /* Update the advertising parameters if necessary */
1972 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001973 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001974
Johan Hedberg2b76f452013-03-15 17:07:04 -05001975 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001976 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001978 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001979 err = set_connectable_update_settings(hdev, sk,
1980 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001981 goto failed;
1982 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001983
1984failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001985 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986 return err;
1987}
1988
Johan Hedbergb2939472014-07-30 09:22:23 +03001989static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001990 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001991{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001992 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001993 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001994 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001996 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001997
Johan Hedberga7e80f22013-01-09 16:05:19 +02001998 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001999 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2000 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002001
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002002 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002003
2004 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002005 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002006 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03002007 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002008
Johan Hedbergb2939472014-07-30 09:22:23 +03002009 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002010 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002011 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002012
Marcel Holtmann55594352013-10-06 16:11:57 -07002013 if (changed)
2014 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002015
Marcel Holtmann55594352013-10-06 16:11:57 -07002016unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002017 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002018 return err;
2019}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002020
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002021static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2022 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002023{
2024 struct mgmt_mode *cp = data;
2025 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002026 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002027 int err;
2028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002029 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002030
Johan Hedberge6fe7982013-10-02 15:45:22 +03002031 status = mgmt_bredr_support(hdev);
2032 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002033 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2034 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002035
Johan Hedberga7e80f22013-01-09 16:05:19 +02002036 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002037 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2038 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002039
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002040 hci_dev_lock(hdev);
2041
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002042 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002043 bool changed = false;
2044
2045 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002046 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002047 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2048 changed = true;
2049 }
2050
2051 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2052 if (err < 0)
2053 goto failed;
2054
2055 if (changed)
2056 err = new_settings(hdev, sk);
2057
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002058 goto failed;
2059 }
2060
2061 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002062 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2063 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002064 goto failed;
2065 }
2066
2067 val = !!cp->val;
2068
2069 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2070 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2071 goto failed;
2072 }
2073
2074 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2075 if (!cmd) {
2076 err = -ENOMEM;
2077 goto failed;
2078 }
2079
2080 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2081 if (err < 0) {
2082 mgmt_pending_remove(cmd);
2083 goto failed;
2084 }
2085
2086failed:
2087 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002088 return err;
2089}
2090
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002091static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002092{
2093 struct mgmt_mode *cp = data;
2094 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002095 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002096 int err;
2097
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002098 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002099
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002100 status = mgmt_bredr_support(hdev);
2101 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002102 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002103
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002104 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002105 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2106 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002107
Johan Hedberga7e80f22013-01-09 16:05:19 +02002108 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002109 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2110 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002111
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002112 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002113
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002114 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002115 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002116
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002117 if (cp->val) {
2118 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2119 &hdev->dev_flags);
2120 } else {
2121 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2122 &hdev->dev_flags);
2123 if (!changed)
2124 changed = test_and_clear_bit(HCI_HS_ENABLED,
2125 &hdev->dev_flags);
2126 else
2127 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002128 }
2129
2130 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2131 if (err < 0)
2132 goto failed;
2133
2134 if (changed)
2135 err = new_settings(hdev, sk);
2136
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 goto failed;
2138 }
2139
Johan Hedberg94d52da2015-02-19 17:38:06 +02002140 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002141 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2142 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002143 goto failed;
2144 }
2145
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002146 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002147 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2148 goto failed;
2149 }
2150
2151 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2152 if (!cmd) {
2153 err = -ENOMEM;
2154 goto failed;
2155 }
2156
Johan Hedberg37699722014-06-24 14:00:27 +03002157 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2158 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2159 sizeof(cp->val), &cp->val);
2160
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002161 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002162 if (err < 0) {
2163 mgmt_pending_remove(cmd);
2164 goto failed;
2165 }
2166
2167failed:
2168 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002169 return err;
2170}
2171
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002172static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173{
2174 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002176 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002177 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002179 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002180
Johan Hedberge6fe7982013-10-02 15:45:22 +03002181 status = mgmt_bredr_support(hdev);
2182 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002183 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002184
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002185 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002186 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2187 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002188
2189 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002190 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2191 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002192
Johan Hedberga7e80f22013-01-09 16:05:19 +02002193 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002194 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2195 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002196
Marcel Holtmannee392692013-10-01 22:59:23 -07002197 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002198
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002199 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002200 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2201 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002202 goto unlock;
2203 }
2204
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002205 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002206 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002207 } else {
2208 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002209 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2210 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002211 goto unlock;
2212 }
2213
Marcel Holtmannee392692013-10-01 22:59:23 -07002214 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002215 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002216
2217 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2218 if (err < 0)
2219 goto unlock;
2220
2221 if (changed)
2222 err = new_settings(hdev, sk);
2223
2224unlock:
2225 hci_dev_unlock(hdev);
2226 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002227}
2228
Marcel Holtmann1904a852015-01-11 13:50:44 -08002229static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002230{
2231 struct cmd_lookup match = { NULL, hdev };
2232
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302233 hci_dev_lock(hdev);
2234
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002235 if (status) {
2236 u8 mgmt_err = mgmt_status(status);
2237
2238 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2239 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302240 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002241 }
2242
2243 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2244
2245 new_settings(hdev, match.sk);
2246
2247 if (match.sk)
2248 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002249
2250 /* Make sure the controller has a good default for
2251 * advertising data. Restrict the update to when LE
2252 * has actually been enabled. During power on, the
2253 * update in powered_update_hci will take care of it.
2254 */
2255 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2256 struct hci_request req;
2257
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002258 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002259 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002260 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002261 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002262 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002263 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302264
2265unlock:
2266 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002267}
2268
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002269static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002270{
2271 struct mgmt_mode *cp = data;
2272 struct hci_cp_write_le_host_supported hci_cp;
2273 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002274 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002275 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002276 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002277
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002278 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002279
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002280 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002281 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2282 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002283
Johan Hedberga7e80f22013-01-09 16:05:19 +02002284 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002285 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2286 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002287
Johan Hedbergc73eee92013-04-19 18:35:21 +03002288 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002289 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02002290 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2291 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002292
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002293 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002294
2295 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002296 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002297
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002298 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299 bool changed = false;
2300
2301 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2302 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2303 changed = true;
2304 }
2305
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002306 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2307 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002308 changed = true;
2309 }
2310
Johan Hedberg06199cf2012-02-22 16:37:11 +02002311 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2312 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002313 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002314
2315 if (changed)
2316 err = new_settings(hdev, sk);
2317
Johan Hedberg1de028c2012-02-29 19:55:35 -08002318 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002319 }
2320
Johan Hedberg4375f102013-09-25 13:26:10 +03002321 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2322 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002323 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2324 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002325 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002326 }
2327
2328 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2329 if (!cmd) {
2330 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002331 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002332 }
2333
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002334 hci_req_init(&req, hdev);
2335
Johan Hedberg06199cf2012-02-22 16:37:11 +02002336 memset(&hci_cp, 0, sizeof(hci_cp));
2337
2338 if (val) {
2339 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002340 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002341 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002342 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002343 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002344 }
2345
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002346 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2347 &hci_cp);
2348
2349 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302350 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002351 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002352
Johan Hedberg1de028c2012-02-29 19:55:35 -08002353unlock:
2354 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002355 return err;
2356}
2357
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002358/* This is a helper function to test for pending mgmt commands that can
2359 * cause CoD or EIR HCI commands. We can only allow one such pending
2360 * mgmt command at a time since otherwise we cannot easily track what
2361 * the current values are, will be, and based on that calculate if a new
2362 * HCI command needs to be sent and if yes with what value.
2363 */
2364static bool pending_eir_or_class(struct hci_dev *hdev)
2365{
2366 struct pending_cmd *cmd;
2367
2368 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2369 switch (cmd->opcode) {
2370 case MGMT_OP_ADD_UUID:
2371 case MGMT_OP_REMOVE_UUID:
2372 case MGMT_OP_SET_DEV_CLASS:
2373 case MGMT_OP_SET_POWERED:
2374 return true;
2375 }
2376 }
2377
2378 return false;
2379}
2380
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002381static const u8 bluetooth_base_uuid[] = {
2382 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2383 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2384};
2385
2386static u8 get_uuid_size(const u8 *uuid)
2387{
2388 u32 val;
2389
2390 if (memcmp(uuid, bluetooth_base_uuid, 12))
2391 return 128;
2392
2393 val = get_unaligned_le32(&uuid[12]);
2394 if (val > 0xffff)
2395 return 32;
2396
2397 return 16;
2398}
2399
Johan Hedberg92da6092013-03-15 17:06:55 -05002400static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2401{
2402 struct pending_cmd *cmd;
2403
2404 hci_dev_lock(hdev);
2405
2406 cmd = mgmt_pending_find(mgmt_op, hdev);
2407 if (!cmd)
2408 goto unlock;
2409
2410 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2411 hdev->dev_class, 3);
2412
2413 mgmt_pending_remove(cmd);
2414
2415unlock:
2416 hci_dev_unlock(hdev);
2417}
2418
Marcel Holtmann1904a852015-01-11 13:50:44 -08002419static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002420{
2421 BT_DBG("status 0x%02x", status);
2422
2423 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2424}
2425
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002426static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002427{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002428 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002429 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002430 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002431 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002432 int err;
2433
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002434 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002435
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002436 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002437
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002438 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002439 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2440 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002441 goto failed;
2442 }
2443
Andre Guedes92c4c202012-06-07 19:05:44 -03002444 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002445 if (!uuid) {
2446 err = -ENOMEM;
2447 goto failed;
2448 }
2449
2450 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002451 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002452 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002453
Johan Hedbergde66aa62013-01-27 00:31:27 +02002454 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002455
Johan Hedberg890ea892013-03-15 17:06:52 -05002456 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002457
Johan Hedberg890ea892013-03-15 17:06:52 -05002458 update_class(&req);
2459 update_eir(&req);
2460
Johan Hedberg92da6092013-03-15 17:06:55 -05002461 err = hci_req_run(&req, add_uuid_complete);
2462 if (err < 0) {
2463 if (err != -ENODATA)
2464 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002465
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002466 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002467 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002468 goto failed;
2469 }
2470
2471 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002472 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002473 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002474 goto failed;
2475 }
2476
2477 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002478
2479failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002480 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481 return err;
2482}
2483
Johan Hedberg24b78d02012-02-23 23:24:30 +02002484static bool enable_service_cache(struct hci_dev *hdev)
2485{
2486 if (!hdev_is_powered(hdev))
2487 return false;
2488
2489 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002490 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2491 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002492 return true;
2493 }
2494
2495 return false;
2496}
2497
Marcel Holtmann1904a852015-01-11 13:50:44 -08002498static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002499{
2500 BT_DBG("status 0x%02x", status);
2501
2502 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2503}
2504
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002505static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002506 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002507{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002508 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002509 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002510 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002511 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg890ea892013-03-15 17:06:52 -05002512 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002513 int err, found;
2514
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002515 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002516
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002517 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002518
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002519 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002520 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2521 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002522 goto unlock;
2523 }
2524
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002525 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002526 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002527
Johan Hedberg24b78d02012-02-23 23:24:30 +02002528 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002529 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002530 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002531 goto unlock;
2532 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002533
Johan Hedberg9246a862012-02-23 21:33:16 +02002534 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002535 }
2536
2537 found = 0;
2538
Johan Hedberg056341c2013-01-27 00:31:30 +02002539 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002540 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2541 continue;
2542
2543 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002544 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002545 found++;
2546 }
2547
2548 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002549 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2550 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002551 goto unlock;
2552 }
2553
Johan Hedberg9246a862012-02-23 21:33:16 +02002554update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002555 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002556
Johan Hedberg890ea892013-03-15 17:06:52 -05002557 update_class(&req);
2558 update_eir(&req);
2559
Johan Hedberg92da6092013-03-15 17:06:55 -05002560 err = hci_req_run(&req, remove_uuid_complete);
2561 if (err < 0) {
2562 if (err != -ENODATA)
2563 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002564
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002565 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002566 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002567 goto unlock;
2568 }
2569
2570 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002571 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002572 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002573 goto unlock;
2574 }
2575
2576 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002577
2578unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002579 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002580 return err;
2581}
2582
Marcel Holtmann1904a852015-01-11 13:50:44 -08002583static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002584{
2585 BT_DBG("status 0x%02x", status);
2586
2587 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2588}
2589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002590static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002591 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002592{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002593 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002594 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002595 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002596 int err;
2597
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002598 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002599
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002600 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002601 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2602 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002603
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002604 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002605
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002606 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002607 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2608 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002609 goto unlock;
2610 }
2611
2612 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002613 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2614 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002615 goto unlock;
2616 }
2617
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002618 hdev->major_class = cp->major;
2619 hdev->minor_class = cp->minor;
2620
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002621 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002622 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002623 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002624 goto unlock;
2625 }
2626
Johan Hedberg890ea892013-03-15 17:06:52 -05002627 hci_req_init(&req, hdev);
2628
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002629 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002630 hci_dev_unlock(hdev);
2631 cancel_delayed_work_sync(&hdev->service_cache);
2632 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002633 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002634 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002635
Johan Hedberg890ea892013-03-15 17:06:52 -05002636 update_class(&req);
2637
Johan Hedberg92da6092013-03-15 17:06:55 -05002638 err = hci_req_run(&req, set_class_complete);
2639 if (err < 0) {
2640 if (err != -ENODATA)
2641 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002642
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002643 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002644 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002645 goto unlock;
2646 }
2647
2648 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002649 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002650 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002651 goto unlock;
2652 }
2653
2654 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002655
Johan Hedbergb5235a62012-02-21 14:32:24 +02002656unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002657 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002658 return err;
2659}
2660
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002661static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002662 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002663{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002664 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002665 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2666 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002667 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002668 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002669 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002670
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002671 BT_DBG("request for %s", hdev->name);
2672
2673 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002674 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2675 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002676
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002677 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002678 if (key_count > max_key_count) {
2679 BT_ERR("load_link_keys: too big key_count value %u",
2680 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002681 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2682 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002683 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002684
Johan Hedberg86742e12011-11-07 23:13:38 +02002685 expected_len = sizeof(*cp) + key_count *
2686 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002687 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002688 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002689 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002690 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2691 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002692 }
2693
Johan Hedberg4ae14302013-01-20 14:27:13 +02002694 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002695 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2696 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002697
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002698 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002699 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002700
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002701 for (i = 0; i < key_count; i++) {
2702 struct mgmt_link_key_info *key = &cp->keys[i];
2703
Marcel Holtmann8e991132014-01-10 02:07:25 -08002704 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002705 return mgmt_cmd_status(sk, hdev->id,
2706 MGMT_OP_LOAD_LINK_KEYS,
2707 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002708 }
2709
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002710 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711
2712 hci_link_keys_clear(hdev);
2713
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002714 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002715 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2716 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002717 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002718 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2719 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002720
2721 if (changed)
2722 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002723
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002724 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002725 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726
Johan Hedberg58e92932014-06-24 14:00:26 +03002727 /* Always ignore debug keys and require a new pairing if
2728 * the user wants to use them.
2729 */
2730 if (key->type == HCI_LK_DEBUG_COMBINATION)
2731 continue;
2732
Johan Hedberg7652ff62014-06-24 13:15:49 +03002733 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2734 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002735 }
2736
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002737 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002738
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002739 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002740
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002741 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002742}
2743
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002744static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002745 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002746{
2747 struct mgmt_ev_device_unpaired ev;
2748
2749 bacpy(&ev.addr.bdaddr, bdaddr);
2750 ev.addr.type = addr_type;
2751
2752 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002753 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002754}
2755
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002756static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002757 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002758{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002759 struct mgmt_cp_unpair_device *cp = data;
2760 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002761 struct hci_cp_disconnect dc;
2762 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002763 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002764 int err;
2765
Johan Hedberga8a1d192011-11-10 15:54:38 +02002766 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002767 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2768 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002769
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002770 if (!bdaddr_type_is_valid(cp->addr.type))
2771 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2772 MGMT_STATUS_INVALID_PARAMS,
2773 &rp, sizeof(rp));
2774
Johan Hedberg118da702013-01-20 14:27:20 +02002775 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2776 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2777 MGMT_STATUS_INVALID_PARAMS,
2778 &rp, sizeof(rp));
2779
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002780 hci_dev_lock(hdev);
2781
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002782 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002783 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002784 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002785 goto unlock;
2786 }
2787
Johan Hedberge0b2b272014-02-18 17:14:31 +02002788 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002789 /* If disconnection is requested, then look up the
2790 * connection. If the remote device is connected, it
2791 * will be later used to terminate the link.
2792 *
2793 * Setting it to NULL explicitly will cause no
2794 * termination of the link.
2795 */
2796 if (cp->disconnect)
2797 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2798 &cp->addr.bdaddr);
2799 else
2800 conn = NULL;
2801
Johan Hedberg124f6e32012-02-09 13:50:12 +02002802 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002803 } else {
2804 u8 addr_type;
2805
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002806 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2807 &cp->addr.bdaddr);
2808 if (conn) {
2809 /* Defer clearing up the connection parameters
2810 * until closing to give a chance of keeping
2811 * them if a repairing happens.
2812 */
2813 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2814
2815 /* If disconnection is not requested, then
2816 * clear the connection variable so that the
2817 * link is not terminated.
2818 */
2819 if (!cp->disconnect)
2820 conn = NULL;
2821 }
2822
Johan Hedberge0b2b272014-02-18 17:14:31 +02002823 if (cp->addr.type == BDADDR_LE_PUBLIC)
2824 addr_type = ADDR_LE_DEV_PUBLIC;
2825 else
2826 addr_type = ADDR_LE_DEV_RANDOM;
2827
Johan Hedberga7ec7332014-02-18 17:14:35 +02002828 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2829
Johan Hedberge0b2b272014-02-18 17:14:31 +02002830 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2831 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002832
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002833 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002834 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002835 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002836 goto unlock;
2837 }
2838
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002839 /* If the connection variable is set, then termination of the
2840 * link is requested.
2841 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002842 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002843 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002844 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002845 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002846 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002847 }
2848
Johan Hedberg124f6e32012-02-09 13:50:12 +02002849 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002850 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002851 if (!cmd) {
2852 err = -ENOMEM;
2853 goto unlock;
2854 }
2855
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002856 cmd->cmd_complete = addr_cmd_complete;
2857
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002858 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002859 dc.reason = 0x13; /* Remote User Terminated Connection */
2860 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2861 if (err < 0)
2862 mgmt_pending_remove(cmd);
2863
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002864unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002865 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002866 return err;
2867}
2868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002869static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002870 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002871{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002872 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002873 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002874 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002875 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002876 int err;
2877
2878 BT_DBG("");
2879
Johan Hedberg06a63b12013-01-20 14:27:21 +02002880 memset(&rp, 0, sizeof(rp));
2881 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2882 rp.addr.type = cp->addr.type;
2883
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002884 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002885 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2886 MGMT_STATUS_INVALID_PARAMS,
2887 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002888
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002889 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002890
2891 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002892 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2893 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002894 goto failed;
2895 }
2896
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002897 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002898 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2899 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002900 goto failed;
2901 }
2902
Andre Guedes591f47f2012-04-24 21:02:49 -03002903 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002904 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2905 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002906 else
2907 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002908
Vishal Agarwalf9607272012-06-13 05:32:43 +05302909 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002910 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2911 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002912 goto failed;
2913 }
2914
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002915 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002916 if (!cmd) {
2917 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002918 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002919 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002920
Johan Hedbergf5818c22014-12-05 13:36:02 +02002921 cmd->cmd_complete = generic_cmd_complete;
2922
Johan Hedberge3f2f922014-08-18 20:33:33 +03002923 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002924 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002925 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002926
2927failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002928 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002929 return err;
2930}
2931
Andre Guedes57c14772012-04-24 21:02:50 -03002932static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002933{
2934 switch (link_type) {
2935 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002936 switch (addr_type) {
2937 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002938 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002939
Johan Hedberg48264f02011-11-09 13:58:58 +02002940 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002941 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002942 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002943 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002944
Johan Hedberg4c659c32011-11-07 23:13:39 +02002945 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002946 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002947 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002948 }
2949}
2950
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002951static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2952 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002953{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002954 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002955 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002956 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002957 int err;
2958 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002959
2960 BT_DBG("");
2961
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002962 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002963
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002964 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002965 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2966 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002967 goto unlock;
2968 }
2969
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002970 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002971 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2972 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002973 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002974 }
2975
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002976 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002977 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002978 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002979 err = -ENOMEM;
2980 goto unlock;
2981 }
2982
Johan Hedberg2784eb42011-01-21 13:56:35 +02002983 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002984 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002985 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2986 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002987 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002988 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002989 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002990 continue;
2991 i++;
2992 }
2993
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002994 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002995
Johan Hedberg4c659c32011-11-07 23:13:39 +02002996 /* Recalculate length in case of filtered SCO connections, etc */
2997 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002998
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002999 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003000 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003001
Johan Hedberga38528f2011-01-22 06:46:43 +02003002 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003003
3004unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003005 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003006 return err;
3007}
3008
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003009static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003010 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003011{
3012 struct pending_cmd *cmd;
3013 int err;
3014
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003015 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003016 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003017 if (!cmd)
3018 return -ENOMEM;
3019
Johan Hedbergd8457692012-02-17 14:24:57 +02003020 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003021 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003022 if (err < 0)
3023 mgmt_pending_remove(cmd);
3024
3025 return err;
3026}
3027
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003028static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003029 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003030{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003031 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003032 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003033 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003034 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003035 int err;
3036
3037 BT_DBG("");
3038
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003039 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003041 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003042 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3043 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003044 goto failed;
3045 }
3046
Johan Hedbergd8457692012-02-17 14:24:57 +02003047 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003048 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003049 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3050 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003051 goto failed;
3052 }
3053
3054 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003055 struct mgmt_cp_pin_code_neg_reply ncp;
3056
3057 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003058
3059 BT_ERR("PIN code is not 16 bytes long");
3060
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003061 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003062 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003063 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3064 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003065
3066 goto failed;
3067 }
3068
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003069 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003070 if (!cmd) {
3071 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003072 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003073 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003074
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003075 cmd->cmd_complete = addr_cmd_complete;
3076
Johan Hedbergd8457692012-02-17 14:24:57 +02003077 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003078 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003079 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003080
3081 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3082 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003083 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003084
3085failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003086 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003087 return err;
3088}
3089
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003090static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3091 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003092{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003093 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003094
3095 BT_DBG("");
3096
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003097 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3098 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3099 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3100
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003101 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003102
3103 hdev->io_capability = cp->io_capability;
3104
3105 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003106 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003107
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003108 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003109
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003110 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3111 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003112}
3113
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003114static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003115{
3116 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003117 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003118
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003119 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003120 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3121 continue;
3122
Johan Hedberge9a416b2011-02-19 12:05:56 -03003123 if (cmd->user_data != conn)
3124 continue;
3125
3126 return cmd;
3127 }
3128
3129 return NULL;
3130}
3131
Johan Hedberg9df74652014-12-19 22:26:03 +02003132static int pairing_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003133{
3134 struct mgmt_rp_pair_device rp;
3135 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003136 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003138 bacpy(&rp.addr.bdaddr, &conn->dst);
3139 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003140
Johan Hedberg9df74652014-12-19 22:26:03 +02003141 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
3142 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003143
3144 /* So we don't get further callbacks for this connection */
3145 conn->connect_cfm_cb = NULL;
3146 conn->security_cfm_cb = NULL;
3147 conn->disconn_cfm_cb = NULL;
3148
David Herrmann76a68ba2013-04-06 20:28:37 +02003149 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003150
3151 /* The device is paired so there is no need to remove
3152 * its connection parameters anymore.
3153 */
3154 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003155
3156 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003157
3158 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003159}
3160
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003161void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3162{
3163 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3164 struct pending_cmd *cmd;
3165
3166 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003167 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003168 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003169 mgmt_pending_remove(cmd);
3170 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003171}
3172
Johan Hedberge9a416b2011-02-19 12:05:56 -03003173static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3174{
3175 struct pending_cmd *cmd;
3176
3177 BT_DBG("status %u", status);
3178
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003179 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003180 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003181 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003182 return;
3183 }
3184
3185 cmd->cmd_complete(cmd, mgmt_status(status));
3186 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003187}
3188
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003189static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303190{
3191 struct pending_cmd *cmd;
3192
3193 BT_DBG("status %u", status);
3194
3195 if (!status)
3196 return;
3197
3198 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003199 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303200 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003201 return;
3202 }
3203
3204 cmd->cmd_complete(cmd, mgmt_status(status));
3205 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303206}
3207
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003208static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003209 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003210{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003211 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003212 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003213 struct pending_cmd *cmd;
3214 u8 sec_level, auth_type;
3215 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003216 int err;
3217
3218 BT_DBG("");
3219
Szymon Jancf950a30e2013-01-18 12:48:07 +01003220 memset(&rp, 0, sizeof(rp));
3221 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3222 rp.addr.type = cp->addr.type;
3223
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003224 if (!bdaddr_type_is_valid(cp->addr.type))
3225 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3226 MGMT_STATUS_INVALID_PARAMS,
3227 &rp, sizeof(rp));
3228
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003229 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3230 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3231 MGMT_STATUS_INVALID_PARAMS,
3232 &rp, sizeof(rp));
3233
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003234 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003235
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003236 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003237 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3238 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003239 goto unlock;
3240 }
3241
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003242 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003243 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003244
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003245 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003246 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3247 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003248 } else {
3249 u8 addr_type;
3250
3251 /* Convert from L2CAP channel address type to HCI address type
3252 */
3253 if (cp->addr.type == BDADDR_LE_PUBLIC)
3254 addr_type = ADDR_LE_DEV_PUBLIC;
3255 else
3256 addr_type = ADDR_LE_DEV_RANDOM;
3257
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003258 /* When pairing a new device, it is expected to remember
3259 * this device for future connections. Adding the connection
3260 * parameter information ahead of time allows tracking
3261 * of the slave preferred values and will speed up any
3262 * further connection establishment.
3263 *
3264 * If connection parameters already exist, then they
3265 * will be kept and this function does nothing.
3266 */
3267 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3268
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003269 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003270 sec_level, HCI_LE_CONN_TIMEOUT,
3271 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003272 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003273
Ville Tervo30e76272011-02-22 16:10:53 -03003274 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003275 int status;
3276
3277 if (PTR_ERR(conn) == -EBUSY)
3278 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003279 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3280 status = MGMT_STATUS_NOT_SUPPORTED;
3281 else if (PTR_ERR(conn) == -ECONNREFUSED)
3282 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003283 else
3284 status = MGMT_STATUS_CONNECT_FAILED;
3285
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003286 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003287 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003288 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003289 goto unlock;
3290 }
3291
3292 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003293 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003294 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003295 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003296 goto unlock;
3297 }
3298
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003299 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003300 if (!cmd) {
3301 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003302 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003303 goto unlock;
3304 }
3305
Johan Hedberg04ab2742014-12-05 13:36:04 +02003306 cmd->cmd_complete = pairing_complete;
3307
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003308 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003309 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003310 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003311 conn->security_cfm_cb = pairing_complete_cb;
3312 conn->disconn_cfm_cb = pairing_complete_cb;
3313 } else {
3314 conn->connect_cfm_cb = le_pairing_complete_cb;
3315 conn->security_cfm_cb = le_pairing_complete_cb;
3316 conn->disconn_cfm_cb = le_pairing_complete_cb;
3317 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003318
Johan Hedberge9a416b2011-02-19 12:05:56 -03003319 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003320 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003321
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003322 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003323 hci_conn_security(conn, sec_level, auth_type, true)) {
3324 cmd->cmd_complete(cmd, 0);
3325 mgmt_pending_remove(cmd);
3326 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003327
3328 err = 0;
3329
3330unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003331 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003332 return err;
3333}
3334
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003335static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3336 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003337{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003338 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003339 struct pending_cmd *cmd;
3340 struct hci_conn *conn;
3341 int err;
3342
3343 BT_DBG("");
3344
Johan Hedberg28424702012-02-02 04:02:29 +02003345 hci_dev_lock(hdev);
3346
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003347 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003348 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3349 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003350 goto unlock;
3351 }
3352
Johan Hedberg28424702012-02-02 04:02:29 +02003353 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3354 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003355 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3356 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003357 goto unlock;
3358 }
3359
3360 conn = cmd->user_data;
3361
3362 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003363 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3364 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003365 goto unlock;
3366 }
3367
Johan Hedberga511b352014-12-11 21:45:45 +02003368 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3369 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003370
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003371 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003372 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003373unlock:
3374 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003375 return err;
3376}
3377
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003378static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003379 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003380 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003381{
Johan Hedberga5c29682011-02-19 12:05:57 -03003382 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003383 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003384 int err;
3385
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003386 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003387
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003388 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003389 err = cmd_complete(sk, hdev->id, mgmt_op,
3390 MGMT_STATUS_NOT_POWERED, addr,
3391 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003392 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003393 }
3394
Johan Hedberg1707c602013-03-15 17:07:15 -05003395 if (addr->type == BDADDR_BREDR)
3396 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003397 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003398 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003399
Johan Hedberg272d90d2012-02-09 15:26:12 +02003400 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003401 err = cmd_complete(sk, hdev->id, mgmt_op,
3402 MGMT_STATUS_NOT_CONNECTED, addr,
3403 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003404 goto done;
3405 }
3406
Johan Hedberg1707c602013-03-15 17:07:15 -05003407 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003408 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003409 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003410 err = cmd_complete(sk, hdev->id, mgmt_op,
3411 MGMT_STATUS_SUCCESS, addr,
3412 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003413 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003414 err = cmd_complete(sk, hdev->id, mgmt_op,
3415 MGMT_STATUS_FAILED, addr,
3416 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003417
Brian Gix47c15e22011-11-16 13:53:14 -08003418 goto done;
3419 }
3420
Johan Hedberg1707c602013-03-15 17:07:15 -05003421 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003422 if (!cmd) {
3423 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003424 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003425 }
3426
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003427 cmd->cmd_complete = addr_cmd_complete;
3428
Brian Gix0df4c182011-11-16 13:53:13 -08003429 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003430 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3431 struct hci_cp_user_passkey_reply cp;
3432
Johan Hedberg1707c602013-03-15 17:07:15 -05003433 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003434 cp.passkey = passkey;
3435 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3436 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003437 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3438 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003439
Johan Hedberga664b5b2011-02-19 12:06:02 -03003440 if (err < 0)
3441 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003442
Brian Gix0df4c182011-11-16 13:53:13 -08003443done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003444 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003445 return err;
3446}
3447
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303448static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3449 void *data, u16 len)
3450{
3451 struct mgmt_cp_pin_code_neg_reply *cp = data;
3452
3453 BT_DBG("");
3454
Johan Hedberg1707c602013-03-15 17:07:15 -05003455 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303456 MGMT_OP_PIN_CODE_NEG_REPLY,
3457 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3458}
3459
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003460static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3461 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003462{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003463 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003464
3465 BT_DBG("");
3466
3467 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003468 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3469 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003470
Johan Hedberg1707c602013-03-15 17:07:15 -05003471 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003472 MGMT_OP_USER_CONFIRM_REPLY,
3473 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003474}
3475
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003476static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003477 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003478{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003479 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003480
3481 BT_DBG("");
3482
Johan Hedberg1707c602013-03-15 17:07:15 -05003483 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3485 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003486}
3487
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003488static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3489 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003490{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003491 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003492
3493 BT_DBG("");
3494
Johan Hedberg1707c602013-03-15 17:07:15 -05003495 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003496 MGMT_OP_USER_PASSKEY_REPLY,
3497 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003498}
3499
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003500static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003501 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003502{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003503 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003504
3505 BT_DBG("");
3506
Johan Hedberg1707c602013-03-15 17:07:15 -05003507 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003508 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3509 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003510}
3511
Johan Hedberg13928972013-03-15 17:07:00 -05003512static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003513{
Johan Hedberg13928972013-03-15 17:07:00 -05003514 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003515 struct hci_cp_write_local_name cp;
3516
Johan Hedberg13928972013-03-15 17:07:00 -05003517 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003518
Johan Hedberg890ea892013-03-15 17:06:52 -05003519 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003520}
3521
Marcel Holtmann1904a852015-01-11 13:50:44 -08003522static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003523{
3524 struct mgmt_cp_set_local_name *cp;
3525 struct pending_cmd *cmd;
3526
3527 BT_DBG("status 0x%02x", status);
3528
3529 hci_dev_lock(hdev);
3530
3531 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3532 if (!cmd)
3533 goto unlock;
3534
3535 cp = cmd->param;
3536
3537 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003538 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3539 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003540 else
3541 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3542 cp, sizeof(*cp));
3543
3544 mgmt_pending_remove(cmd);
3545
3546unlock:
3547 hci_dev_unlock(hdev);
3548}
3549
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003550static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003551 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003552{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003553 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003554 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003555 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003556 int err;
3557
3558 BT_DBG("");
3559
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003560 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003561
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003562 /* If the old values are the same as the new ones just return a
3563 * direct command complete event.
3564 */
3565 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3566 !memcmp(hdev->short_name, cp->short_name,
3567 sizeof(hdev->short_name))) {
3568 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3569 data, len);
3570 goto failed;
3571 }
3572
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003573 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003574
Johan Hedbergb5235a62012-02-21 14:32:24 +02003575 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003576 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003577
3578 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003579 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003580 if (err < 0)
3581 goto failed;
3582
3583 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003584 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003585
Johan Hedbergb5235a62012-02-21 14:32:24 +02003586 goto failed;
3587 }
3588
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003589 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003590 if (!cmd) {
3591 err = -ENOMEM;
3592 goto failed;
3593 }
3594
Johan Hedberg13928972013-03-15 17:07:00 -05003595 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3596
Johan Hedberg890ea892013-03-15 17:06:52 -05003597 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003598
3599 if (lmp_bredr_capable(hdev)) {
3600 update_name(&req);
3601 update_eir(&req);
3602 }
3603
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003604 /* The name is stored in the scan response data and so
3605 * no need to udpate the advertising data here.
3606 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003607 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003608 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003609
Johan Hedberg13928972013-03-15 17:07:00 -05003610 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003611 if (err < 0)
3612 mgmt_pending_remove(cmd);
3613
3614failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003615 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003616 return err;
3617}
3618
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003619static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003620 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003621{
Szymon Jancc35938b2011-03-22 13:12:21 +01003622 struct pending_cmd *cmd;
3623 int err;
3624
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003625 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003626
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003627 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003628
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003629 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003630 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3631 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003632 goto unlock;
3633 }
3634
Andre Guedes9a1a1992012-07-24 15:03:48 -03003635 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003636 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3637 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003638 goto unlock;
3639 }
3640
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003641 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003642 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3643 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003644 goto unlock;
3645 }
3646
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003647 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003648 if (!cmd) {
3649 err = -ENOMEM;
3650 goto unlock;
3651 }
3652
Johan Hedberg710f11c2014-05-26 11:21:22 +03003653 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003654 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3655 0, NULL);
3656 else
3657 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3658
Szymon Jancc35938b2011-03-22 13:12:21 +01003659 if (err < 0)
3660 mgmt_pending_remove(cmd);
3661
3662unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003663 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003664 return err;
3665}
3666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003667static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003668 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003669{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003670 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003671 int err;
3672
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003673 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003674
Johan Hedberg5d57e792015-01-23 10:10:38 +02003675 if (!bdaddr_type_is_valid(addr->type))
3676 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3677 MGMT_STATUS_INVALID_PARAMS, addr,
3678 sizeof(*addr));
3679
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003680 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003681
Marcel Holtmannec109112014-01-10 02:07:30 -08003682 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3683 struct mgmt_cp_add_remote_oob_data *cp = data;
3684 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003685
Johan Hedbergc19a4952014-11-17 20:52:19 +02003686 if (cp->addr.type != BDADDR_BREDR) {
3687 err = cmd_complete(sk, hdev->id,
3688 MGMT_OP_ADD_REMOTE_OOB_DATA,
3689 MGMT_STATUS_INVALID_PARAMS,
3690 &cp->addr, sizeof(cp->addr));
3691 goto unlock;
3692 }
3693
Marcel Holtmannec109112014-01-10 02:07:30 -08003694 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003695 cp->addr.type, cp->hash,
3696 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003697 if (err < 0)
3698 status = MGMT_STATUS_FAILED;
3699 else
3700 status = MGMT_STATUS_SUCCESS;
3701
3702 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3703 status, &cp->addr, sizeof(cp->addr));
3704 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3705 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003706 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003707 u8 status;
3708
Johan Hedberg86df9202014-10-26 20:52:27 +01003709 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003710 /* Enforce zero-valued 192-bit parameters as
3711 * long as legacy SMP OOB isn't implemented.
3712 */
3713 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3714 memcmp(cp->hash192, ZERO_KEY, 16)) {
3715 err = cmd_complete(sk, hdev->id,
3716 MGMT_OP_ADD_REMOTE_OOB_DATA,
3717 MGMT_STATUS_INVALID_PARAMS,
3718 addr, sizeof(*addr));
3719 goto unlock;
3720 }
3721
Johan Hedberg86df9202014-10-26 20:52:27 +01003722 rand192 = NULL;
3723 hash192 = NULL;
3724 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003725 /* In case one of the P-192 values is set to zero,
3726 * then just disable OOB data for P-192.
3727 */
3728 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3729 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3730 rand192 = NULL;
3731 hash192 = NULL;
3732 } else {
3733 rand192 = cp->rand192;
3734 hash192 = cp->hash192;
3735 }
3736 }
3737
3738 /* In case one of the P-256 values is set to zero, then just
3739 * disable OOB data for P-256.
3740 */
3741 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3742 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3743 rand256 = NULL;
3744 hash256 = NULL;
3745 } else {
3746 rand256 = cp->rand256;
3747 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003748 }
3749
Johan Hedberg81328d52014-10-26 20:33:47 +01003750 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003751 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003752 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003753 if (err < 0)
3754 status = MGMT_STATUS_FAILED;
3755 else
3756 status = MGMT_STATUS_SUCCESS;
3757
3758 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3759 status, &cp->addr, sizeof(cp->addr));
3760 } else {
3761 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003762 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3763 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003764 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003765
Johan Hedbergc19a4952014-11-17 20:52:19 +02003766unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003767 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003768 return err;
3769}
3770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003771static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003772 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003773{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003774 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003775 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003776 int err;
3777
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003778 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003779
Johan Hedbergc19a4952014-11-17 20:52:19 +02003780 if (cp->addr.type != BDADDR_BREDR)
3781 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3782 MGMT_STATUS_INVALID_PARAMS,
3783 &cp->addr, sizeof(cp->addr));
3784
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003785 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003786
Johan Hedbergeedbd582014-11-15 09:34:23 +02003787 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3788 hci_remote_oob_data_clear(hdev);
3789 status = MGMT_STATUS_SUCCESS;
3790 goto done;
3791 }
3792
Johan Hedberg6928a922014-10-26 20:46:09 +01003793 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003794 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003795 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003796 else
Szymon Janca6785be2012-12-13 15:11:21 +01003797 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003798
Johan Hedbergeedbd582014-11-15 09:34:23 +02003799done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003800 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003801 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003802
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003803 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003804 return err;
3805}
3806
Marcel Holtmann80190442014-12-04 11:36:36 +01003807static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003808{
Marcel Holtmann80190442014-12-04 11:36:36 +01003809 struct hci_dev *hdev = req->hdev;
3810 struct hci_cp_le_set_scan_param param_cp;
3811 struct hci_cp_le_set_scan_enable enable_cp;
3812 struct hci_cp_inquiry inq_cp;
3813 /* General inquiry access code (GIAC) */
3814 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3815 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003816 int err;
3817
Marcel Holtmann80190442014-12-04 11:36:36 +01003818 switch (hdev->discovery.type) {
3819 case DISCOV_TYPE_BREDR:
3820 *status = mgmt_bredr_support(hdev);
3821 if (*status)
3822 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003823
Marcel Holtmann80190442014-12-04 11:36:36 +01003824 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3825 *status = MGMT_STATUS_BUSY;
3826 return false;
3827 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003828
Marcel Holtmann80190442014-12-04 11:36:36 +01003829 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003830
Marcel Holtmann80190442014-12-04 11:36:36 +01003831 memset(&inq_cp, 0, sizeof(inq_cp));
3832 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3833 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3834 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3835 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003836
Marcel Holtmann80190442014-12-04 11:36:36 +01003837 case DISCOV_TYPE_LE:
3838 case DISCOV_TYPE_INTERLEAVED:
3839 *status = mgmt_le_support(hdev);
3840 if (*status)
3841 return false;
3842
3843 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3844 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3845 *status = MGMT_STATUS_NOT_SUPPORTED;
3846 return false;
3847 }
3848
3849 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3850 /* Don't let discovery abort an outgoing
3851 * connection attempt that's using directed
3852 * advertising.
3853 */
3854 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3855 BT_CONNECT)) {
3856 *status = MGMT_STATUS_REJECTED;
3857 return false;
3858 }
3859
3860 disable_advertising(req);
3861 }
3862
3863 /* If controller is scanning, it means the background scanning
3864 * is running. Thus, we should temporarily stop it in order to
3865 * set the discovery scanning parameters.
3866 */
3867 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3868 hci_req_add_le_scan_disable(req);
3869
3870 memset(&param_cp, 0, sizeof(param_cp));
3871
3872 /* All active scans will be done with either a resolvable
3873 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003874 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003875 */
3876 err = hci_update_random_address(req, true, &own_addr_type);
3877 if (err < 0) {
3878 *status = MGMT_STATUS_FAILED;
3879 return false;
3880 }
3881
3882 param_cp.type = LE_SCAN_ACTIVE;
3883 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3884 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3885 param_cp.own_address_type = own_addr_type;
3886 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3887 &param_cp);
3888
3889 memset(&enable_cp, 0, sizeof(enable_cp));
3890 enable_cp.enable = LE_SCAN_ENABLE;
3891 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3892 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3893 &enable_cp);
3894 break;
3895
3896 default:
3897 *status = MGMT_STATUS_INVALID_PARAMS;
3898 return false;
3899 }
3900
3901 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003902}
3903
Marcel Holtmann1904a852015-01-11 13:50:44 -08003904static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3905 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003906{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003907 struct pending_cmd *cmd;
3908 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003909
Andre Guedes7c307722013-04-30 15:29:28 -03003910 BT_DBG("status %d", status);
3911
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003912 hci_dev_lock(hdev);
3913
3914 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003915 if (!cmd)
3916 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3917
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003918 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003919 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003920 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003921 }
3922
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003923 if (status) {
3924 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3925 goto unlock;
3926 }
3927
Andre Guedes7c307722013-04-30 15:29:28 -03003928 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003929
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003930 /* If the scan involves LE scan, pick proper timeout to schedule
3931 * hdev->le_scan_disable that will stop it.
3932 */
Andre Guedes7c307722013-04-30 15:29:28 -03003933 switch (hdev->discovery.type) {
3934 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003935 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003936 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003937 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003938 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003939 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003940 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003941 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003942 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003943 default:
3944 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003945 timeout = 0;
3946 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003947 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003948
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003949 if (timeout) {
3950 /* When service discovery is used and the controller has
3951 * a strict duplicate filter, it is important to remember
3952 * the start and duration of the scan. This is required
3953 * for restarting scanning during the discovery phase.
3954 */
3955 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3956 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003957 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003958 hdev->discovery.scan_start = jiffies;
3959 hdev->discovery.scan_duration = timeout;
3960 }
3961
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003962 queue_delayed_work(hdev->workqueue,
3963 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003964 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003965
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003966unlock:
3967 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003968}
3969
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003970static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003971 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003972{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003973 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003974 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003975 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003976 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003977 int err;
3978
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003979 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003980
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003981 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003982
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003983 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003984 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3985 MGMT_STATUS_NOT_POWERED,
3986 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003987 goto failed;
3988 }
3989
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003990 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3991 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003992 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3993 MGMT_STATUS_BUSY, &cp->type,
3994 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003995 goto failed;
3996 }
3997
Johan Hedberg2922a942014-12-05 13:36:06 +02003998 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003999 if (!cmd) {
4000 err = -ENOMEM;
4001 goto failed;
4002 }
4003
Johan Hedberg2922a942014-12-05 13:36:06 +02004004 cmd->cmd_complete = generic_cmd_complete;
4005
Marcel Holtmann22078802014-12-05 11:45:22 +01004006 /* Clear the discovery filter first to free any previously
4007 * allocated memory for the UUID list.
4008 */
4009 hci_discovery_filter_clear(hdev);
4010
Andre Guedes4aab14e2012-02-17 20:39:36 -03004011 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004012 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004013
Andre Guedes7c307722013-04-30 15:29:28 -03004014 hci_req_init(&req, hdev);
4015
Marcel Holtmann80190442014-12-04 11:36:36 +01004016 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01004017 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01004018 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004019 mgmt_pending_remove(cmd);
4020 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004021 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004022
Andre Guedes7c307722013-04-30 15:29:28 -03004023 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004024 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004025 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004026 goto failed;
4027 }
4028
4029 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004030
4031failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004032 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004033 return err;
4034}
4035
Johan Hedberg9df74652014-12-19 22:26:03 +02004036static int service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004037{
Johan Hedberg9df74652014-12-19 22:26:03 +02004038 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4039 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004040}
4041
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004042static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4043 void *data, u16 len)
4044{
4045 struct mgmt_cp_start_service_discovery *cp = data;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004046 struct pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004047 struct hci_request req;
4048 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4049 u16 uuid_count, expected_len;
4050 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004051 int err;
4052
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004053 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004054
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004055 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004056
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004057 if (!hdev_is_powered(hdev)) {
4058 err = cmd_complete(sk, hdev->id,
4059 MGMT_OP_START_SERVICE_DISCOVERY,
4060 MGMT_STATUS_NOT_POWERED,
4061 &cp->type, sizeof(cp->type));
4062 goto failed;
4063 }
4064
4065 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4066 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
4067 err = cmd_complete(sk, hdev->id,
4068 MGMT_OP_START_SERVICE_DISCOVERY,
4069 MGMT_STATUS_BUSY, &cp->type,
4070 sizeof(cp->type));
4071 goto failed;
4072 }
4073
4074 uuid_count = __le16_to_cpu(cp->uuid_count);
4075 if (uuid_count > max_uuid_count) {
4076 BT_ERR("service_discovery: too big uuid_count value %u",
4077 uuid_count);
4078 err = cmd_complete(sk, hdev->id,
4079 MGMT_OP_START_SERVICE_DISCOVERY,
4080 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4081 sizeof(cp->type));
4082 goto failed;
4083 }
4084
4085 expected_len = sizeof(*cp) + uuid_count * 16;
4086 if (expected_len != len) {
4087 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4088 expected_len, len);
4089 err = cmd_complete(sk, hdev->id,
4090 MGMT_OP_START_SERVICE_DISCOVERY,
4091 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4092 sizeof(cp->type));
4093 goto failed;
4094 }
4095
4096 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004097 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004098 if (!cmd) {
4099 err = -ENOMEM;
4100 goto failed;
4101 }
4102
Johan Hedberg2922a942014-12-05 13:36:06 +02004103 cmd->cmd_complete = service_discovery_cmd_complete;
4104
Marcel Holtmann22078802014-12-05 11:45:22 +01004105 /* Clear the discovery filter first to free any previously
4106 * allocated memory for the UUID list.
4107 */
4108 hci_discovery_filter_clear(hdev);
4109
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004110 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004111 hdev->discovery.type = cp->type;
4112 hdev->discovery.rssi = cp->rssi;
4113 hdev->discovery.uuid_count = uuid_count;
4114
4115 if (uuid_count > 0) {
4116 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4117 GFP_KERNEL);
4118 if (!hdev->discovery.uuids) {
4119 err = cmd_complete(sk, hdev->id,
4120 MGMT_OP_START_SERVICE_DISCOVERY,
4121 MGMT_STATUS_FAILED,
4122 &cp->type, sizeof(cp->type));
4123 mgmt_pending_remove(cmd);
4124 goto failed;
4125 }
4126 }
4127
4128 hci_req_init(&req, hdev);
4129
4130 if (!trigger_discovery(&req, &status)) {
4131 err = cmd_complete(sk, hdev->id,
4132 MGMT_OP_START_SERVICE_DISCOVERY,
4133 status, &cp->type, sizeof(cp->type));
4134 mgmt_pending_remove(cmd);
4135 goto failed;
4136 }
4137
4138 err = hci_req_run(&req, start_discovery_complete);
4139 if (err < 0) {
4140 mgmt_pending_remove(cmd);
4141 goto failed;
4142 }
4143
4144 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4145
4146failed:
4147 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004148 return err;
4149}
4150
Marcel Holtmann1904a852015-01-11 13:50:44 -08004151static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004152{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004153 struct pending_cmd *cmd;
4154
Andre Guedes0e05bba2013-04-30 15:29:33 -03004155 BT_DBG("status %d", status);
4156
4157 hci_dev_lock(hdev);
4158
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004159 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4160 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004161 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004162 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004163 }
4164
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004165 if (!status)
4166 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004167
Andre Guedes0e05bba2013-04-30 15:29:33 -03004168 hci_dev_unlock(hdev);
4169}
4170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004171static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004172 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004173{
Johan Hedbergd9306502012-02-20 23:25:18 +02004174 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004175 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004176 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004177 int err;
4178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004179 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004180
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004181 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004182
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004183 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004184 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004185 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4186 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004187 goto unlock;
4188 }
4189
4190 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004191 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004192 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4193 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004194 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004195 }
4196
Johan Hedberg2922a942014-12-05 13:36:06 +02004197 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004198 if (!cmd) {
4199 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004200 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004201 }
4202
Johan Hedberg2922a942014-12-05 13:36:06 +02004203 cmd->cmd_complete = generic_cmd_complete;
4204
Andre Guedes0e05bba2013-04-30 15:29:33 -03004205 hci_req_init(&req, hdev);
4206
Johan Hedberg21a60d32014-06-10 14:05:58 +03004207 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004208
Johan Hedberg21a60d32014-06-10 14:05:58 +03004209 err = hci_req_run(&req, stop_discovery_complete);
4210 if (!err) {
4211 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004212 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004213 }
4214
Johan Hedberg21a60d32014-06-10 14:05:58 +03004215 mgmt_pending_remove(cmd);
4216
4217 /* If no HCI commands were sent we're done */
4218 if (err == -ENODATA) {
4219 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4220 &mgmt_cp->type, sizeof(mgmt_cp->type));
4221 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4222 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004223
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004224unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004225 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004226 return err;
4227}
4228
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004229static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004230 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004231{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004232 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004233 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004234 int err;
4235
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004236 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004237
Johan Hedberg561aafb2012-01-04 13:31:59 +02004238 hci_dev_lock(hdev);
4239
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004240 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004241 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4242 MGMT_STATUS_FAILED, &cp->addr,
4243 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004244 goto failed;
4245 }
4246
Johan Hedberga198e7b2012-02-17 14:27:06 +02004247 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004248 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004249 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4250 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4251 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004252 goto failed;
4253 }
4254
4255 if (cp->name_known) {
4256 e->name_state = NAME_KNOWN;
4257 list_del(&e->list);
4258 } else {
4259 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004260 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004261 }
4262
Johan Hedberge3846622013-01-09 15:29:33 +02004263 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4264 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004265
4266failed:
4267 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004268 return err;
4269}
4270
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004271static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004272 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004273{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004274 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004275 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004276 int err;
4277
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004278 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004279
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004280 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004281 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4282 MGMT_STATUS_INVALID_PARAMS,
4283 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004284
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004285 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004286
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004287 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4288 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004289 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004290 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004291 goto done;
4292 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004293
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004294 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4295 sk);
4296 status = MGMT_STATUS_SUCCESS;
4297
4298done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004299 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004300 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004301
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004302 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004303
4304 return err;
4305}
4306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004307static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004308 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004309{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004310 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004311 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004312 int err;
4313
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004314 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004315
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004316 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004317 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4318 MGMT_STATUS_INVALID_PARAMS,
4319 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004320
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004321 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004322
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004323 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4324 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004325 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004326 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004327 goto done;
4328 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004329
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004330 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4331 sk);
4332 status = MGMT_STATUS_SUCCESS;
4333
4334done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004335 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004336 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004337
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004338 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004339
4340 return err;
4341}
4342
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004343static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4344 u16 len)
4345{
4346 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004347 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004348 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004349 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004350
4351 BT_DBG("%s", hdev->name);
4352
Szymon Jancc72d4b82012-03-16 16:02:57 +01004353 source = __le16_to_cpu(cp->source);
4354
4355 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004356 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4357 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004358
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004359 hci_dev_lock(hdev);
4360
Szymon Jancc72d4b82012-03-16 16:02:57 +01004361 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004362 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4363 hdev->devid_product = __le16_to_cpu(cp->product);
4364 hdev->devid_version = __le16_to_cpu(cp->version);
4365
4366 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4367
Johan Hedberg890ea892013-03-15 17:06:52 -05004368 hci_req_init(&req, hdev);
4369 update_eir(&req);
4370 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004371
4372 hci_dev_unlock(hdev);
4373
4374 return err;
4375}
4376
Marcel Holtmann1904a852015-01-11 13:50:44 -08004377static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4378 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004379{
4380 struct cmd_lookup match = { NULL, hdev };
4381
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304382 hci_dev_lock(hdev);
4383
Johan Hedberg4375f102013-09-25 13:26:10 +03004384 if (status) {
4385 u8 mgmt_err = mgmt_status(status);
4386
4387 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4388 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304389 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004390 }
4391
Johan Hedbergc93bd152014-07-08 15:07:48 +03004392 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4393 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4394 else
4395 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4396
Johan Hedberg4375f102013-09-25 13:26:10 +03004397 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4398 &match);
4399
4400 new_settings(hdev, match.sk);
4401
4402 if (match.sk)
4403 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304404
4405unlock:
4406 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004407}
4408
Marcel Holtmann21b51872013-10-10 09:47:53 -07004409static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4410 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004411{
4412 struct mgmt_mode *cp = data;
4413 struct pending_cmd *cmd;
4414 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004415 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004416 int err;
4417
4418 BT_DBG("request for %s", hdev->name);
4419
Johan Hedberge6fe7982013-10-02 15:45:22 +03004420 status = mgmt_le_support(hdev);
4421 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004422 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4423 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004424
4425 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004426 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4427 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004428
4429 hci_dev_lock(hdev);
4430
4431 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004432 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004433
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004434 /* The following conditions are ones which mean that we should
4435 * not do any HCI communication but directly send a mgmt
4436 * response to user space (after toggling the flag if
4437 * necessary).
4438 */
4439 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004440 hci_conn_num(hdev, LE_LINK) > 0 ||
4441 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4442 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004443 bool changed = false;
4444
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004445 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4446 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004447 changed = true;
4448 }
4449
4450 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4451 if (err < 0)
4452 goto unlock;
4453
4454 if (changed)
4455 err = new_settings(hdev, sk);
4456
4457 goto unlock;
4458 }
4459
4460 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4461 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004462 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4463 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004464 goto unlock;
4465 }
4466
4467 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4468 if (!cmd) {
4469 err = -ENOMEM;
4470 goto unlock;
4471 }
4472
4473 hci_req_init(&req, hdev);
4474
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004475 if (val)
4476 enable_advertising(&req);
4477 else
4478 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004479
4480 err = hci_req_run(&req, set_advertising_complete);
4481 if (err < 0)
4482 mgmt_pending_remove(cmd);
4483
4484unlock:
4485 hci_dev_unlock(hdev);
4486 return err;
4487}
4488
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004489static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4490 void *data, u16 len)
4491{
4492 struct mgmt_cp_set_static_address *cp = data;
4493 int err;
4494
4495 BT_DBG("%s", hdev->name);
4496
Marcel Holtmann62af4442013-10-02 22:10:32 -07004497 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004498 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4499 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004500
4501 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004502 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4503 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004504
4505 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4506 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004507 return mgmt_cmd_status(sk, hdev->id,
4508 MGMT_OP_SET_STATIC_ADDRESS,
4509 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004510
4511 /* Two most significant bits shall be set */
4512 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004513 return mgmt_cmd_status(sk, hdev->id,
4514 MGMT_OP_SET_STATIC_ADDRESS,
4515 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004516 }
4517
4518 hci_dev_lock(hdev);
4519
4520 bacpy(&hdev->static_addr, &cp->bdaddr);
4521
Marcel Holtmann93690c22015-03-06 10:11:21 -08004522 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4523 if (err < 0)
4524 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004525
Marcel Holtmann93690c22015-03-06 10:11:21 -08004526 err = new_settings(hdev, sk);
4527
4528unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004529 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004530 return err;
4531}
4532
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004533static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4534 void *data, u16 len)
4535{
4536 struct mgmt_cp_set_scan_params *cp = data;
4537 __u16 interval, window;
4538 int err;
4539
4540 BT_DBG("%s", hdev->name);
4541
4542 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004543 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4544 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004545
4546 interval = __le16_to_cpu(cp->interval);
4547
4548 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004549 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4550 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004551
4552 window = __le16_to_cpu(cp->window);
4553
4554 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004555 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4556 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004557
Marcel Holtmann899e1072013-10-14 09:55:32 -07004558 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004559 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4560 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004561
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004562 hci_dev_lock(hdev);
4563
4564 hdev->le_scan_interval = interval;
4565 hdev->le_scan_window = window;
4566
4567 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4568
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004569 /* If background scan is running, restart it so new parameters are
4570 * loaded.
4571 */
4572 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4573 hdev->discovery.state == DISCOVERY_STOPPED) {
4574 struct hci_request req;
4575
4576 hci_req_init(&req, hdev);
4577
4578 hci_req_add_le_scan_disable(&req);
4579 hci_req_add_le_passive_scan(&req);
4580
4581 hci_req_run(&req, NULL);
4582 }
4583
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004584 hci_dev_unlock(hdev);
4585
4586 return err;
4587}
4588
Marcel Holtmann1904a852015-01-11 13:50:44 -08004589static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4590 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004591{
4592 struct pending_cmd *cmd;
4593
4594 BT_DBG("status 0x%02x", status);
4595
4596 hci_dev_lock(hdev);
4597
4598 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4599 if (!cmd)
4600 goto unlock;
4601
4602 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004603 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4604 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004605 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004606 struct mgmt_mode *cp = cmd->param;
4607
4608 if (cp->val)
4609 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4610 else
4611 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4612
Johan Hedberg33e38b32013-03-15 17:07:05 -05004613 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4614 new_settings(hdev, cmd->sk);
4615 }
4616
4617 mgmt_pending_remove(cmd);
4618
4619unlock:
4620 hci_dev_unlock(hdev);
4621}
4622
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004623static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004624 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004625{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004626 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004627 struct pending_cmd *cmd;
4628 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004629 int err;
4630
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004631 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004632
Johan Hedberg56f87902013-10-02 13:43:13 +03004633 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4634 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004635 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4636 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004637
Johan Hedberga7e80f22013-01-09 16:05:19 +02004638 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004639 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4640 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004641
Johan Hedberg5400c042012-02-21 16:40:33 +02004642 if (!hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004643 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4644 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004645
4646 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004647 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4648 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004649
4650 hci_dev_lock(hdev);
4651
Johan Hedberg05cbf292013-03-15 17:07:07 -05004652 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004653 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4654 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004655 goto unlock;
4656 }
4657
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004658 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4659 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4660 hdev);
4661 goto unlock;
4662 }
4663
Johan Hedberg33e38b32013-03-15 17:07:05 -05004664 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4665 data, len);
4666 if (!cmd) {
4667 err = -ENOMEM;
4668 goto unlock;
4669 }
4670
4671 hci_req_init(&req, hdev);
4672
Johan Hedberg406d7802013-03-15 17:07:09 -05004673 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004674
4675 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004676 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004677 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4678 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004679 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004680 }
4681
Johan Hedberg33e38b32013-03-15 17:07:05 -05004682unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004683 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004684
Antti Julkuf6422ec2011-06-22 13:11:56 +03004685 return err;
4686}
4687
Marcel Holtmann1904a852015-01-11 13:50:44 -08004688static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004689{
4690 struct pending_cmd *cmd;
4691
4692 BT_DBG("status 0x%02x", status);
4693
4694 hci_dev_lock(hdev);
4695
4696 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4697 if (!cmd)
4698 goto unlock;
4699
4700 if (status) {
4701 u8 mgmt_err = mgmt_status(status);
4702
4703 /* We need to restore the flag if related HCI commands
4704 * failed.
4705 */
4706 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4707
Johan Hedberga69e8372015-03-06 21:08:53 +02004708 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004709 } else {
4710 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4711 new_settings(hdev, cmd->sk);
4712 }
4713
4714 mgmt_pending_remove(cmd);
4715
4716unlock:
4717 hci_dev_unlock(hdev);
4718}
4719
4720static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4721{
4722 struct mgmt_mode *cp = data;
4723 struct pending_cmd *cmd;
4724 struct hci_request req;
4725 int err;
4726
4727 BT_DBG("request for %s", hdev->name);
4728
4729 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004730 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4731 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004732
4733 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004734 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4735 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004736
4737 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004738 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4739 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004740
4741 hci_dev_lock(hdev);
4742
4743 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4744 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4745 goto unlock;
4746 }
4747
4748 if (!hdev_is_powered(hdev)) {
4749 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004750 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4751 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4752 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4753 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4754 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4755 }
4756
4757 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4758
4759 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4760 if (err < 0)
4761 goto unlock;
4762
4763 err = new_settings(hdev, sk);
4764 goto unlock;
4765 }
4766
4767 /* Reject disabling when powered on */
4768 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004769 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4770 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004771 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004772 } else {
4773 /* When configuring a dual-mode controller to operate
4774 * with LE only and using a static address, then switching
4775 * BR/EDR back on is not allowed.
4776 *
4777 * Dual-mode controllers shall operate with the public
4778 * address as its identity address for BR/EDR and LE. So
4779 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004780 *
4781 * The same restrictions applies when secure connections
4782 * has been enabled. For BR/EDR this is a controller feature
4783 * while for LE it is a host stack feature. This means that
4784 * switching BR/EDR back on when secure connections has been
4785 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004786 */
4787 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004788 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4789 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004790 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4791 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004792 goto unlock;
4793 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004794 }
4795
4796 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004797 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4798 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004799 goto unlock;
4800 }
4801
4802 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4803 if (!cmd) {
4804 err = -ENOMEM;
4805 goto unlock;
4806 }
4807
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004808 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004809 * generates the correct flags.
4810 */
4811 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4812
4813 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004814
Johan Hedberg432df052014-08-01 11:13:31 +03004815 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004816 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004817
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004818 /* Since only the advertising data flags will change, there
4819 * is no need to update the scan response data.
4820 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004821 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004822
Johan Hedberg0663ca22013-10-02 13:43:14 +03004823 err = hci_req_run(&req, set_bredr_complete);
4824 if (err < 0)
4825 mgmt_pending_remove(cmd);
4826
4827unlock:
4828 hci_dev_unlock(hdev);
4829 return err;
4830}
4831
Johan Hedberga1443f52015-01-23 15:42:46 +02004832static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4833{
4834 struct pending_cmd *cmd;
4835 struct mgmt_mode *cp;
4836
4837 BT_DBG("%s status %u", hdev->name, status);
4838
4839 hci_dev_lock(hdev);
4840
4841 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4842 if (!cmd)
4843 goto unlock;
4844
4845 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004846 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4847 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004848 goto remove;
4849 }
4850
4851 cp = cmd->param;
4852
4853 switch (cp->val) {
4854 case 0x00:
4855 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4856 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4857 break;
4858 case 0x01:
4859 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4860 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4861 break;
4862 case 0x02:
4863 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4864 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4865 break;
4866 }
4867
4868 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4869 new_settings(hdev, cmd->sk);
4870
4871remove:
4872 mgmt_pending_remove(cmd);
4873unlock:
4874 hci_dev_unlock(hdev);
4875}
4876
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004877static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4878 void *data, u16 len)
4879{
4880 struct mgmt_mode *cp = data;
4881 struct pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004882 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004883 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004884 int err;
4885
4886 BT_DBG("request for %s", hdev->name);
4887
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004888 if (!lmp_sc_capable(hdev) &&
4889 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004890 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4891 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004892
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004893 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004894 lmp_sc_capable(hdev) &&
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004895 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberga69e8372015-03-06 21:08:53 +02004896 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4897 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004898
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004899 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004900 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004901 MGMT_STATUS_INVALID_PARAMS);
4902
4903 hci_dev_lock(hdev);
4904
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004905 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004906 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004907 bool changed;
4908
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004909 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004910 changed = !test_and_set_bit(HCI_SC_ENABLED,
4911 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004912 if (cp->val == 0x02)
4913 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4914 else
4915 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4916 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004917 changed = test_and_clear_bit(HCI_SC_ENABLED,
4918 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004919 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4920 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004921
4922 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4923 if (err < 0)
4924 goto failed;
4925
4926 if (changed)
4927 err = new_settings(hdev, sk);
4928
4929 goto failed;
4930 }
4931
4932 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004933 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4934 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004935 goto failed;
4936 }
4937
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004938 val = !!cp->val;
4939
4940 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4941 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004942 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4943 goto failed;
4944 }
4945
4946 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4947 if (!cmd) {
4948 err = -ENOMEM;
4949 goto failed;
4950 }
4951
Johan Hedberga1443f52015-01-23 15:42:46 +02004952 hci_req_init(&req, hdev);
4953 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4954 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004955 if (err < 0) {
4956 mgmt_pending_remove(cmd);
4957 goto failed;
4958 }
4959
4960failed:
4961 hci_dev_unlock(hdev);
4962 return err;
4963}
4964
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004965static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4966 void *data, u16 len)
4967{
4968 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004969 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004970 int err;
4971
4972 BT_DBG("request for %s", hdev->name);
4973
Johan Hedbergb97109792014-06-24 14:00:28 +03004974 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004975 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4976 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004977
4978 hci_dev_lock(hdev);
4979
4980 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004981 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4982 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004983 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004984 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4985 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004986
Johan Hedbergb97109792014-06-24 14:00:28 +03004987 if (cp->val == 0x02)
4988 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4989 &hdev->dev_flags);
4990 else
4991 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4992 &hdev->dev_flags);
4993
4994 if (hdev_is_powered(hdev) && use_changed &&
4995 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4996 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4997 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4998 sizeof(mode), &mode);
4999 }
5000
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005001 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5002 if (err < 0)
5003 goto unlock;
5004
5005 if (changed)
5006 err = new_settings(hdev, sk);
5007
5008unlock:
5009 hci_dev_unlock(hdev);
5010 return err;
5011}
5012
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005013static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5014 u16 len)
5015{
5016 struct mgmt_cp_set_privacy *cp = cp_data;
5017 bool changed;
5018 int err;
5019
5020 BT_DBG("request for %s", hdev->name);
5021
5022 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005023 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5024 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005025
5026 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005027 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5028 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005029
5030 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005031 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5032 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005033
5034 hci_dev_lock(hdev);
5035
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005036 /* If user space supports this command it is also expected to
5037 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5038 */
5039 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5040
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005041 if (cp->privacy) {
5042 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5043 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5044 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5045 } else {
5046 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5047 memset(hdev->irk, 0, sizeof(hdev->irk));
5048 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5049 }
5050
5051 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5052 if (err < 0)
5053 goto unlock;
5054
5055 if (changed)
5056 err = new_settings(hdev, sk);
5057
5058unlock:
5059 hci_dev_unlock(hdev);
5060 return err;
5061}
5062
Johan Hedberg41edf162014-02-18 10:19:35 +02005063static bool irk_is_valid(struct mgmt_irk_info *irk)
5064{
5065 switch (irk->addr.type) {
5066 case BDADDR_LE_PUBLIC:
5067 return true;
5068
5069 case BDADDR_LE_RANDOM:
5070 /* Two most significant bits shall be set */
5071 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5072 return false;
5073 return true;
5074 }
5075
5076 return false;
5077}
5078
5079static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5080 u16 len)
5081{
5082 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005083 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5084 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005085 u16 irk_count, expected_len;
5086 int i, err;
5087
5088 BT_DBG("request for %s", hdev->name);
5089
5090 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005091 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5092 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005093
5094 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005095 if (irk_count > max_irk_count) {
5096 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005097 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5098 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005099 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005100
5101 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5102 if (expected_len != len) {
5103 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005104 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005105 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5106 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005107 }
5108
5109 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5110
5111 for (i = 0; i < irk_count; i++) {
5112 struct mgmt_irk_info *key = &cp->irks[i];
5113
5114 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005115 return mgmt_cmd_status(sk, hdev->id,
5116 MGMT_OP_LOAD_IRKS,
5117 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005118 }
5119
5120 hci_dev_lock(hdev);
5121
5122 hci_smp_irks_clear(hdev);
5123
5124 for (i = 0; i < irk_count; i++) {
5125 struct mgmt_irk_info *irk = &cp->irks[i];
5126 u8 addr_type;
5127
5128 if (irk->addr.type == BDADDR_LE_PUBLIC)
5129 addr_type = ADDR_LE_DEV_PUBLIC;
5130 else
5131 addr_type = ADDR_LE_DEV_RANDOM;
5132
5133 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5134 BDADDR_ANY);
5135 }
5136
5137 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5138
5139 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
5140
5141 hci_dev_unlock(hdev);
5142
5143 return err;
5144}
5145
Johan Hedberg3f706b72013-01-20 14:27:16 +02005146static bool ltk_is_valid(struct mgmt_ltk_info *key)
5147{
5148 if (key->master != 0x00 && key->master != 0x01)
5149 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005150
5151 switch (key->addr.type) {
5152 case BDADDR_LE_PUBLIC:
5153 return true;
5154
5155 case BDADDR_LE_RANDOM:
5156 /* Two most significant bits shall be set */
5157 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5158 return false;
5159 return true;
5160 }
5161
5162 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005163}
5164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005165static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005166 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005167{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005168 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005169 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5170 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005171 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005172 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005173
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005174 BT_DBG("request for %s", hdev->name);
5175
5176 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005177 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5178 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005179
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005180 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005181 if (key_count > max_key_count) {
5182 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005183 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5184 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005185 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005186
5187 expected_len = sizeof(*cp) + key_count *
5188 sizeof(struct mgmt_ltk_info);
5189 if (expected_len != len) {
5190 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005191 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005192 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5193 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005194 }
5195
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005196 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005197
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005198 for (i = 0; i < key_count; i++) {
5199 struct mgmt_ltk_info *key = &cp->keys[i];
5200
Johan Hedberg3f706b72013-01-20 14:27:16 +02005201 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005202 return mgmt_cmd_status(sk, hdev->id,
5203 MGMT_OP_LOAD_LONG_TERM_KEYS,
5204 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005205 }
5206
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005207 hci_dev_lock(hdev);
5208
5209 hci_smp_ltks_clear(hdev);
5210
5211 for (i = 0; i < key_count; i++) {
5212 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005213 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005214
5215 if (key->addr.type == BDADDR_LE_PUBLIC)
5216 addr_type = ADDR_LE_DEV_PUBLIC;
5217 else
5218 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005219
Johan Hedberg61b43352014-05-29 19:36:53 +03005220 switch (key->type) {
5221 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005222 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005223 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005224 break;
5225 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005226 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005227 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005228 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005229 case MGMT_LTK_P256_UNAUTH:
5230 authenticated = 0x00;
5231 type = SMP_LTK_P256;
5232 break;
5233 case MGMT_LTK_P256_AUTH:
5234 authenticated = 0x01;
5235 type = SMP_LTK_P256;
5236 break;
5237 case MGMT_LTK_P256_DEBUG:
5238 authenticated = 0x00;
5239 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005240 default:
5241 continue;
5242 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005243
Johan Hedberg35d70272014-02-19 14:57:47 +02005244 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005245 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005246 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005247 }
5248
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005249 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5250 NULL, 0);
5251
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005252 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005253
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005254 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005255}
5256
Johan Hedberg9df74652014-12-19 22:26:03 +02005257static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005258{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005259 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005260 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005261 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005262
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005263 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005264
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005265 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005266 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005267 rp.tx_power = conn->tx_power;
5268 rp.max_tx_power = conn->max_tx_power;
5269 } else {
5270 rp.rssi = HCI_RSSI_INVALID;
5271 rp.tx_power = HCI_TX_POWER_INVALID;
5272 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005273 }
5274
Johan Hedberg9df74652014-12-19 22:26:03 +02005275 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5276 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005277
5278 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005279 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005280
5281 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005282}
5283
Marcel Holtmann1904a852015-01-11 13:50:44 -08005284static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5285 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005286{
5287 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005288 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005289 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005290 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005291 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005292
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005293 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005294
5295 hci_dev_lock(hdev);
5296
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005297 /* Commands sent in request are either Read RSSI or Read Transmit Power
5298 * Level so we check which one was last sent to retrieve connection
5299 * handle. Both commands have handle as first parameter so it's safe to
5300 * cast data on the same command struct.
5301 *
5302 * First command sent is always Read RSSI and we fail only if it fails.
5303 * In other case we simply override error to indicate success as we
5304 * already remembered if TX power value is actually valid.
5305 */
5306 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5307 if (!cp) {
5308 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005309 status = MGMT_STATUS_SUCCESS;
5310 } else {
5311 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005312 }
5313
5314 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005315 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005316 goto unlock;
5317 }
5318
5319 handle = __le16_to_cpu(cp->handle);
5320 conn = hci_conn_hash_lookup_handle(hdev, handle);
5321 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005322 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005323 goto unlock;
5324 }
5325
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005326 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5327 if (!cmd)
5328 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005329
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005330 cmd->cmd_complete(cmd, status);
5331 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005332
5333unlock:
5334 hci_dev_unlock(hdev);
5335}
5336
5337static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5338 u16 len)
5339{
5340 struct mgmt_cp_get_conn_info *cp = data;
5341 struct mgmt_rp_get_conn_info rp;
5342 struct hci_conn *conn;
5343 unsigned long conn_info_age;
5344 int err = 0;
5345
5346 BT_DBG("%s", hdev->name);
5347
5348 memset(&rp, 0, sizeof(rp));
5349 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5350 rp.addr.type = cp->addr.type;
5351
5352 if (!bdaddr_type_is_valid(cp->addr.type))
5353 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5354 MGMT_STATUS_INVALID_PARAMS,
5355 &rp, sizeof(rp));
5356
5357 hci_dev_lock(hdev);
5358
5359 if (!hdev_is_powered(hdev)) {
5360 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5361 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5362 goto unlock;
5363 }
5364
5365 if (cp->addr.type == BDADDR_BREDR)
5366 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5367 &cp->addr.bdaddr);
5368 else
5369 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5370
5371 if (!conn || conn->state != BT_CONNECTED) {
5372 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5373 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5374 goto unlock;
5375 }
5376
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005377 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5378 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5379 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5380 goto unlock;
5381 }
5382
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005383 /* To avoid client trying to guess when to poll again for information we
5384 * calculate conn info age as random value between min/max set in hdev.
5385 */
5386 conn_info_age = hdev->conn_info_min_age +
5387 prandom_u32_max(hdev->conn_info_max_age -
5388 hdev->conn_info_min_age);
5389
5390 /* Query controller to refresh cached values if they are too old or were
5391 * never read.
5392 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005393 if (time_after(jiffies, conn->conn_info_timestamp +
5394 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005395 !conn->conn_info_timestamp) {
5396 struct hci_request req;
5397 struct hci_cp_read_tx_power req_txp_cp;
5398 struct hci_cp_read_rssi req_rssi_cp;
5399 struct pending_cmd *cmd;
5400
5401 hci_req_init(&req, hdev);
5402 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5403 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5404 &req_rssi_cp);
5405
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005406 /* For LE links TX power does not change thus we don't need to
5407 * query for it once value is known.
5408 */
5409 if (!bdaddr_type_is_le(cp->addr.type) ||
5410 conn->tx_power == HCI_TX_POWER_INVALID) {
5411 req_txp_cp.handle = cpu_to_le16(conn->handle);
5412 req_txp_cp.type = 0x00;
5413 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5414 sizeof(req_txp_cp), &req_txp_cp);
5415 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005416
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005417 /* Max TX power needs to be read only once per connection */
5418 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5419 req_txp_cp.handle = cpu_to_le16(conn->handle);
5420 req_txp_cp.type = 0x01;
5421 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5422 sizeof(req_txp_cp), &req_txp_cp);
5423 }
5424
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005425 err = hci_req_run(&req, conn_info_refresh_complete);
5426 if (err < 0)
5427 goto unlock;
5428
5429 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5430 data, len);
5431 if (!cmd) {
5432 err = -ENOMEM;
5433 goto unlock;
5434 }
5435
5436 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005437 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005438 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005439
5440 conn->conn_info_timestamp = jiffies;
5441 } else {
5442 /* Cache is valid, just reply with values cached in hci_conn */
5443 rp.rssi = conn->rssi;
5444 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005445 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005446
5447 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5448 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5449 }
5450
5451unlock:
5452 hci_dev_unlock(hdev);
5453 return err;
5454}
5455
Johan Hedberg9df74652014-12-19 22:26:03 +02005456static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005457{
5458 struct hci_conn *conn = cmd->user_data;
5459 struct mgmt_rp_get_clock_info rp;
5460 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005461 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005462
5463 memset(&rp, 0, sizeof(rp));
5464 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5465
5466 if (status)
5467 goto complete;
5468
5469 hdev = hci_dev_get(cmd->index);
5470 if (hdev) {
5471 rp.local_clock = cpu_to_le32(hdev->clock);
5472 hci_dev_put(hdev);
5473 }
5474
5475 if (conn) {
5476 rp.piconet_clock = cpu_to_le32(conn->clock);
5477 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5478 }
5479
5480complete:
Johan Hedberg9df74652014-12-19 22:26:03 +02005481 err = cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5482 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005483
5484 if (conn) {
5485 hci_conn_drop(conn);
5486 hci_conn_put(conn);
5487 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005488
5489 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005490}
5491
Marcel Holtmann1904a852015-01-11 13:50:44 -08005492static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005493{
Johan Hedberg95868422014-06-28 17:54:07 +03005494 struct hci_cp_read_clock *hci_cp;
5495 struct pending_cmd *cmd;
5496 struct hci_conn *conn;
5497
5498 BT_DBG("%s status %u", hdev->name, status);
5499
5500 hci_dev_lock(hdev);
5501
5502 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5503 if (!hci_cp)
5504 goto unlock;
5505
5506 if (hci_cp->which) {
5507 u16 handle = __le16_to_cpu(hci_cp->handle);
5508 conn = hci_conn_hash_lookup_handle(hdev, handle);
5509 } else {
5510 conn = NULL;
5511 }
5512
5513 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5514 if (!cmd)
5515 goto unlock;
5516
Johan Hedberg69487372014-12-05 13:36:07 +02005517 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005518 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005519
5520unlock:
5521 hci_dev_unlock(hdev);
5522}
5523
5524static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5525 u16 len)
5526{
5527 struct mgmt_cp_get_clock_info *cp = data;
5528 struct mgmt_rp_get_clock_info rp;
5529 struct hci_cp_read_clock hci_cp;
5530 struct pending_cmd *cmd;
5531 struct hci_request req;
5532 struct hci_conn *conn;
5533 int err;
5534
5535 BT_DBG("%s", hdev->name);
5536
5537 memset(&rp, 0, sizeof(rp));
5538 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5539 rp.addr.type = cp->addr.type;
5540
5541 if (cp->addr.type != BDADDR_BREDR)
5542 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5543 MGMT_STATUS_INVALID_PARAMS,
5544 &rp, sizeof(rp));
5545
5546 hci_dev_lock(hdev);
5547
5548 if (!hdev_is_powered(hdev)) {
5549 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5550 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5551 goto unlock;
5552 }
5553
5554 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5555 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5556 &cp->addr.bdaddr);
5557 if (!conn || conn->state != BT_CONNECTED) {
5558 err = cmd_complete(sk, hdev->id,
5559 MGMT_OP_GET_CLOCK_INFO,
5560 MGMT_STATUS_NOT_CONNECTED,
5561 &rp, sizeof(rp));
5562 goto unlock;
5563 }
5564 } else {
5565 conn = NULL;
5566 }
5567
5568 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5569 if (!cmd) {
5570 err = -ENOMEM;
5571 goto unlock;
5572 }
5573
Johan Hedberg69487372014-12-05 13:36:07 +02005574 cmd->cmd_complete = clock_info_cmd_complete;
5575
Johan Hedberg95868422014-06-28 17:54:07 +03005576 hci_req_init(&req, hdev);
5577
5578 memset(&hci_cp, 0, sizeof(hci_cp));
5579 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5580
5581 if (conn) {
5582 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005583 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005584
5585 hci_cp.handle = cpu_to_le16(conn->handle);
5586 hci_cp.which = 0x01; /* Piconet clock */
5587 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5588 }
5589
5590 err = hci_req_run(&req, get_clock_info_complete);
5591 if (err < 0)
5592 mgmt_pending_remove(cmd);
5593
5594unlock:
5595 hci_dev_unlock(hdev);
5596 return err;
5597}
5598
Johan Hedberg5a154e62014-12-19 22:26:02 +02005599static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5600{
5601 struct hci_conn *conn;
5602
5603 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5604 if (!conn)
5605 return false;
5606
5607 if (conn->dst_type != type)
5608 return false;
5609
5610 if (conn->state != BT_CONNECTED)
5611 return false;
5612
5613 return true;
5614}
5615
5616/* This function requires the caller holds hdev->lock */
5617static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5618 u8 addr_type, u8 auto_connect)
5619{
5620 struct hci_dev *hdev = req->hdev;
5621 struct hci_conn_params *params;
5622
5623 params = hci_conn_params_add(hdev, addr, addr_type);
5624 if (!params)
5625 return -EIO;
5626
5627 if (params->auto_connect == auto_connect)
5628 return 0;
5629
5630 list_del_init(&params->action);
5631
5632 switch (auto_connect) {
5633 case HCI_AUTO_CONN_DISABLED:
5634 case HCI_AUTO_CONN_LINK_LOSS:
5635 __hci_update_background_scan(req);
5636 break;
5637 case HCI_AUTO_CONN_REPORT:
5638 list_add(&params->action, &hdev->pend_le_reports);
5639 __hci_update_background_scan(req);
5640 break;
5641 case HCI_AUTO_CONN_DIRECT:
5642 case HCI_AUTO_CONN_ALWAYS:
5643 if (!is_connected(hdev, addr, addr_type)) {
5644 list_add(&params->action, &hdev->pend_le_conns);
5645 __hci_update_background_scan(req);
5646 }
5647 break;
5648 }
5649
5650 params->auto_connect = auto_connect;
5651
5652 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5653 auto_connect);
5654
5655 return 0;
5656}
5657
Marcel Holtmann8afef092014-06-29 22:28:34 +02005658static void device_added(struct sock *sk, struct hci_dev *hdev,
5659 bdaddr_t *bdaddr, u8 type, u8 action)
5660{
5661 struct mgmt_ev_device_added ev;
5662
5663 bacpy(&ev.addr.bdaddr, bdaddr);
5664 ev.addr.type = type;
5665 ev.action = action;
5666
5667 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5668}
5669
Marcel Holtmann1904a852015-01-11 13:50:44 -08005670static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005671{
5672 struct pending_cmd *cmd;
5673
5674 BT_DBG("status 0x%02x", status);
5675
5676 hci_dev_lock(hdev);
5677
5678 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5679 if (!cmd)
5680 goto unlock;
5681
5682 cmd->cmd_complete(cmd, mgmt_status(status));
5683 mgmt_pending_remove(cmd);
5684
5685unlock:
5686 hci_dev_unlock(hdev);
5687}
5688
Marcel Holtmann2faade52014-06-29 19:44:03 +02005689static int add_device(struct sock *sk, struct hci_dev *hdev,
5690 void *data, u16 len)
5691{
5692 struct mgmt_cp_add_device *cp = data;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005693 struct pending_cmd *cmd;
5694 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005695 u8 auto_conn, addr_type;
5696 int err;
5697
5698 BT_DBG("%s", hdev->name);
5699
Johan Hedberg66593582014-07-09 12:59:14 +03005700 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005701 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5702 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5703 MGMT_STATUS_INVALID_PARAMS,
5704 &cp->addr, sizeof(cp->addr));
5705
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005706 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005707 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5708 MGMT_STATUS_INVALID_PARAMS,
5709 &cp->addr, sizeof(cp->addr));
5710
Johan Hedberg5a154e62014-12-19 22:26:02 +02005711 hci_req_init(&req, hdev);
5712
Marcel Holtmann2faade52014-06-29 19:44:03 +02005713 hci_dev_lock(hdev);
5714
Johan Hedberg5a154e62014-12-19 22:26:02 +02005715 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5716 if (!cmd) {
5717 err = -ENOMEM;
5718 goto unlock;
5719 }
5720
5721 cmd->cmd_complete = addr_cmd_complete;
5722
Johan Hedberg66593582014-07-09 12:59:14 +03005723 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005724 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005725 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005726 err = cmd->cmd_complete(cmd,
5727 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005728 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005729 goto unlock;
5730 }
5731
5732 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5733 cp->addr.type);
5734 if (err)
5735 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005736
Johan Hedberg5a154e62014-12-19 22:26:02 +02005737 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005738
Johan Hedberg66593582014-07-09 12:59:14 +03005739 goto added;
5740 }
5741
Marcel Holtmann2faade52014-06-29 19:44:03 +02005742 if (cp->addr.type == BDADDR_LE_PUBLIC)
5743 addr_type = ADDR_LE_DEV_PUBLIC;
5744 else
5745 addr_type = ADDR_LE_DEV_RANDOM;
5746
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005747 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005748 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005749 else if (cp->action == 0x01)
5750 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005751 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005752 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005753
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005754 /* If the connection parameters don't exist for this device,
5755 * they will be created and configured with defaults.
5756 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005757 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005758 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005759 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005760 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005761 goto unlock;
5762 }
5763
Johan Hedberg66593582014-07-09 12:59:14 +03005764added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005765 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5766
Johan Hedberg5a154e62014-12-19 22:26:02 +02005767 err = hci_req_run(&req, add_device_complete);
5768 if (err < 0) {
5769 /* ENODATA means no HCI commands were needed (e.g. if
5770 * the adapter is powered off).
5771 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005772 if (err == -ENODATA)
5773 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005774 mgmt_pending_remove(cmd);
5775 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005776
5777unlock:
5778 hci_dev_unlock(hdev);
5779 return err;
5780}
5781
Marcel Holtmann8afef092014-06-29 22:28:34 +02005782static void device_removed(struct sock *sk, struct hci_dev *hdev,
5783 bdaddr_t *bdaddr, u8 type)
5784{
5785 struct mgmt_ev_device_removed ev;
5786
5787 bacpy(&ev.addr.bdaddr, bdaddr);
5788 ev.addr.type = type;
5789
5790 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5791}
5792
Marcel Holtmann1904a852015-01-11 13:50:44 -08005793static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005794{
5795 struct pending_cmd *cmd;
5796
5797 BT_DBG("status 0x%02x", status);
5798
5799 hci_dev_lock(hdev);
5800
5801 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5802 if (!cmd)
5803 goto unlock;
5804
5805 cmd->cmd_complete(cmd, mgmt_status(status));
5806 mgmt_pending_remove(cmd);
5807
5808unlock:
5809 hci_dev_unlock(hdev);
5810}
5811
Marcel Holtmann2faade52014-06-29 19:44:03 +02005812static int remove_device(struct sock *sk, struct hci_dev *hdev,
5813 void *data, u16 len)
5814{
5815 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005816 struct pending_cmd *cmd;
5817 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005818 int err;
5819
5820 BT_DBG("%s", hdev->name);
5821
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005822 hci_req_init(&req, hdev);
5823
Marcel Holtmann2faade52014-06-29 19:44:03 +02005824 hci_dev_lock(hdev);
5825
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005826 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5827 if (!cmd) {
5828 err = -ENOMEM;
5829 goto unlock;
5830 }
5831
5832 cmd->cmd_complete = addr_cmd_complete;
5833
Marcel Holtmann2faade52014-06-29 19:44:03 +02005834 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005835 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005836 u8 addr_type;
5837
Johan Hedberg66593582014-07-09 12:59:14 +03005838 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005839 err = cmd->cmd_complete(cmd,
5840 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005841 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005842 goto unlock;
5843 }
5844
Johan Hedberg66593582014-07-09 12:59:14 +03005845 if (cp->addr.type == BDADDR_BREDR) {
5846 err = hci_bdaddr_list_del(&hdev->whitelist,
5847 &cp->addr.bdaddr,
5848 cp->addr.type);
5849 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005850 err = cmd->cmd_complete(cmd,
5851 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005852 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005853 goto unlock;
5854 }
5855
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005856 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005857
Johan Hedberg66593582014-07-09 12:59:14 +03005858 device_removed(sk, hdev, &cp->addr.bdaddr,
5859 cp->addr.type);
5860 goto complete;
5861 }
5862
Marcel Holtmann2faade52014-06-29 19:44:03 +02005863 if (cp->addr.type == BDADDR_LE_PUBLIC)
5864 addr_type = ADDR_LE_DEV_PUBLIC;
5865 else
5866 addr_type = ADDR_LE_DEV_RANDOM;
5867
Johan Hedbergc71593d2014-07-02 17:37:28 +03005868 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5869 addr_type);
5870 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005871 err = cmd->cmd_complete(cmd,
5872 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005873 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005874 goto unlock;
5875 }
5876
5877 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005878 err = cmd->cmd_complete(cmd,
5879 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005880 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005881 goto unlock;
5882 }
5883
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005884 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005885 list_del(&params->list);
5886 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005887 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005888
5889 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005890 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005891 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005892 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005893
Marcel Holtmann2faade52014-06-29 19:44:03 +02005894 if (cp->addr.type) {
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);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005898 goto unlock;
5899 }
5900
Johan Hedberg66593582014-07-09 12:59:14 +03005901 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5902 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5903 list_del(&b->list);
5904 kfree(b);
5905 }
5906
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005907 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005908
Johan Hedberg19de0822014-07-06 13:06:51 +03005909 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5910 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5911 continue;
5912 device_removed(sk, hdev, &p->addr, p->addr_type);
5913 list_del(&p->action);
5914 list_del(&p->list);
5915 kfree(p);
5916 }
5917
5918 BT_DBG("All LE connection parameters were removed");
5919
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005920 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005921 }
5922
Johan Hedberg66593582014-07-09 12:59:14 +03005923complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005924 err = hci_req_run(&req, remove_device_complete);
5925 if (err < 0) {
5926 /* ENODATA means no HCI commands were needed (e.g. if
5927 * the adapter is powered off).
5928 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005929 if (err == -ENODATA)
5930 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005931 mgmt_pending_remove(cmd);
5932 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005933
5934unlock:
5935 hci_dev_unlock(hdev);
5936 return err;
5937}
5938
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005939static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5940 u16 len)
5941{
5942 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005943 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5944 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005945 u16 param_count, expected_len;
5946 int i;
5947
5948 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005949 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5950 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005951
5952 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005953 if (param_count > max_param_count) {
5954 BT_ERR("load_conn_param: too big param_count value %u",
5955 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005956 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5957 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005958 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005959
5960 expected_len = sizeof(*cp) + param_count *
5961 sizeof(struct mgmt_conn_param);
5962 if (expected_len != len) {
5963 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5964 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005965 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5966 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005967 }
5968
5969 BT_DBG("%s param_count %u", hdev->name, param_count);
5970
5971 hci_dev_lock(hdev);
5972
5973 hci_conn_params_clear_disabled(hdev);
5974
5975 for (i = 0; i < param_count; i++) {
5976 struct mgmt_conn_param *param = &cp->params[i];
5977 struct hci_conn_params *hci_param;
5978 u16 min, max, latency, timeout;
5979 u8 addr_type;
5980
5981 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5982 param->addr.type);
5983
5984 if (param->addr.type == BDADDR_LE_PUBLIC) {
5985 addr_type = ADDR_LE_DEV_PUBLIC;
5986 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5987 addr_type = ADDR_LE_DEV_RANDOM;
5988 } else {
5989 BT_ERR("Ignoring invalid connection parameters");
5990 continue;
5991 }
5992
5993 min = le16_to_cpu(param->min_interval);
5994 max = le16_to_cpu(param->max_interval);
5995 latency = le16_to_cpu(param->latency);
5996 timeout = le16_to_cpu(param->timeout);
5997
5998 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5999 min, max, latency, timeout);
6000
6001 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6002 BT_ERR("Ignoring invalid connection parameters");
6003 continue;
6004 }
6005
6006 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6007 addr_type);
6008 if (!hci_param) {
6009 BT_ERR("Failed to add connection parameters");
6010 continue;
6011 }
6012
6013 hci_param->conn_min_interval = min;
6014 hci_param->conn_max_interval = max;
6015 hci_param->conn_latency = latency;
6016 hci_param->supervision_timeout = timeout;
6017 }
6018
6019 hci_dev_unlock(hdev);
6020
6021 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
6022}
6023
Marcel Holtmanndbece372014-07-04 18:11:55 +02006024static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6025 void *data, u16 len)
6026{
6027 struct mgmt_cp_set_external_config *cp = data;
6028 bool changed;
6029 int err;
6030
6031 BT_DBG("%s", hdev->name);
6032
6033 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006034 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6035 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006036
6037 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006038 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6039 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006040
6041 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006042 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6043 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006044
6045 hci_dev_lock(hdev);
6046
6047 if (cp->config)
6048 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6049 &hdev->dev_flags);
6050 else
6051 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6052 &hdev->dev_flags);
6053
6054 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6055 if (err < 0)
6056 goto unlock;
6057
6058 if (!changed)
6059 goto unlock;
6060
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006061 err = new_options(hdev, sk);
6062
Marcel Holtmanndbece372014-07-04 18:11:55 +02006063 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
6064 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006065
6066 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6067 set_bit(HCI_CONFIG, &hdev->dev_flags);
6068 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6069
6070 queue_work(hdev->req_workqueue, &hdev->power_on);
6071 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006072 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006073 mgmt_index_added(hdev);
6074 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006075 }
6076
6077unlock:
6078 hci_dev_unlock(hdev);
6079 return err;
6080}
6081
Marcel Holtmann9713c172014-07-06 12:11:15 +02006082static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6083 void *data, u16 len)
6084{
6085 struct mgmt_cp_set_public_address *cp = data;
6086 bool changed;
6087 int err;
6088
6089 BT_DBG("%s", hdev->name);
6090
6091 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006092 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6093 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006094
6095 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006096 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6097 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006098
6099 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006100 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6101 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006102
6103 hci_dev_lock(hdev);
6104
6105 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6106 bacpy(&hdev->public_addr, &cp->bdaddr);
6107
6108 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6109 if (err < 0)
6110 goto unlock;
6111
6112 if (!changed)
6113 goto unlock;
6114
6115 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6116 err = new_options(hdev, sk);
6117
6118 if (is_configured(hdev)) {
6119 mgmt_index_removed(hdev);
6120
6121 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6122
6123 set_bit(HCI_CONFIG, &hdev->dev_flags);
6124 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6125
6126 queue_work(hdev->req_workqueue, &hdev->power_on);
6127 }
6128
6129unlock:
6130 hci_dev_unlock(hdev);
6131 return err;
6132}
6133
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006134static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006135 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006136 { read_version, MGMT_READ_VERSION_SIZE,
6137 HCI_MGMT_NO_HDEV },
6138 { read_commands, MGMT_READ_COMMANDS_SIZE,
6139 HCI_MGMT_NO_HDEV },
6140 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6141 HCI_MGMT_NO_HDEV },
6142 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6143 { set_powered, MGMT_SETTING_SIZE, 0 },
6144 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6145 { set_connectable, MGMT_SETTING_SIZE, 0 },
6146 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6147 { set_bondable, MGMT_SETTING_SIZE, 0 },
6148 { set_link_security, MGMT_SETTING_SIZE, 0 },
6149 { set_ssp, MGMT_SETTING_SIZE, 0 },
6150 { set_hs, MGMT_SETTING_SIZE, 0 },
6151 { set_le, MGMT_SETTING_SIZE, 0 },
6152 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6153 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6154 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6155 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6156 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6157 HCI_MGMT_VAR_LEN },
6158 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6159 HCI_MGMT_VAR_LEN },
6160 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6161 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6162 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6163 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6164 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6165 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6166 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6167 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6168 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6169 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6170 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6171 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6172 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6173 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6174 HCI_MGMT_VAR_LEN },
6175 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6176 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6177 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6178 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6179 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6180 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6181 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6182 { set_advertising, MGMT_SETTING_SIZE, 0 },
6183 { set_bredr, MGMT_SETTING_SIZE, 0 },
6184 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6185 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6186 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6187 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6188 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6189 { load_irks, MGMT_LOAD_IRKS_SIZE,
6190 HCI_MGMT_VAR_LEN },
6191 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6192 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6193 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6194 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6195 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6196 HCI_MGMT_VAR_LEN },
6197 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6198 HCI_MGMT_NO_HDEV },
6199 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6200 HCI_MGMT_UNCONFIGURED },
6201 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6202 HCI_MGMT_UNCONFIGURED },
6203 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6204 HCI_MGMT_UNCONFIGURED },
6205 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6206 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006207};
6208
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006209int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6210 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006211{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006212 void *buf;
6213 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006214 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006215 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006216 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006217 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006218 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006219 int err;
6220
6221 BT_DBG("got %zu bytes", msglen);
6222
6223 if (msglen < sizeof(*hdr))
6224 return -EINVAL;
6225
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006226 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006227 if (!buf)
6228 return -ENOMEM;
6229
Al Viro6ce8e9c2014-04-06 21:25:44 -04006230 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006231 err = -EFAULT;
6232 goto done;
6233 }
6234
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006235 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006236 opcode = __le16_to_cpu(hdr->opcode);
6237 index = __le16_to_cpu(hdr->index);
6238 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006239
6240 if (len != msglen - sizeof(*hdr)) {
6241 err = -EINVAL;
6242 goto done;
6243 }
6244
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006245 if (opcode >= chan->handler_count ||
6246 chan->handlers[opcode].func == NULL) {
6247 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006248 err = mgmt_cmd_status(sk, index, opcode,
6249 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006250 goto done;
6251 }
6252
6253 handler = &chan->handlers[opcode];
6254
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006255 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006256 hdev = hci_dev_get(index);
6257 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006258 err = mgmt_cmd_status(sk, index, opcode,
6259 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006260 goto done;
6261 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006262
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006263 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02006264 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006265 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006266 err = mgmt_cmd_status(sk, index, opcode,
6267 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006268 goto done;
6269 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006270
6271 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006272 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006273 err = mgmt_cmd_status(sk, index, opcode,
6274 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006275 goto done;
6276 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006277 }
6278
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006279 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6280 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006281 err = mgmt_cmd_status(sk, index, opcode,
6282 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006283 goto done;
6284 }
6285
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006286 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6287 if ((var_len && len < handler->data_len) ||
6288 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006289 err = mgmt_cmd_status(sk, index, opcode,
6290 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006291 goto done;
6292 }
6293
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006294 if (hdev)
6295 mgmt_init_hdev(sk, hdev);
6296
6297 cp = buf + sizeof(*hdr);
6298
Johan Hedbergbe22b542012-03-01 22:24:41 +02006299 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006300 if (err < 0)
6301 goto done;
6302
Johan Hedberg03811012010-12-08 00:21:06 +02006303 err = msglen;
6304
6305done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006306 if (hdev)
6307 hci_dev_put(hdev);
6308
Johan Hedberg03811012010-12-08 00:21:06 +02006309 kfree(buf);
6310 return err;
6311}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006312
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006313void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006314{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006315 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006316 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006317
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006318 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6319 return;
6320
6321 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6322 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6323 else
6324 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006325}
6326
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006327void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006328{
Johan Hedberg5f159032012-03-02 03:13:19 +02006329 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006330
Marcel Holtmann1514b892013-10-06 08:25:01 -07006331 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006332 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006333
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006334 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6335 return;
6336
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006337 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006338
Marcel Holtmannedd38962014-07-02 21:30:55 +02006339 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6340 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6341 else
6342 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006343}
6344
Andre Guedes6046dc32014-02-26 20:21:51 -03006345/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006346static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006347{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006348 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006349 struct hci_conn_params *p;
6350
6351 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006352 /* Needed for AUTO_OFF case where might not "really"
6353 * have been powered off.
6354 */
6355 list_del_init(&p->action);
6356
6357 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006358 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006359 case HCI_AUTO_CONN_ALWAYS:
6360 list_add(&p->action, &hdev->pend_le_conns);
6361 break;
6362 case HCI_AUTO_CONN_REPORT:
6363 list_add(&p->action, &hdev->pend_le_reports);
6364 break;
6365 default:
6366 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006367 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006368 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006369
Johan Hedberg2cf22212014-12-19 22:26:00 +02006370 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006371}
6372
Marcel Holtmann1904a852015-01-11 13:50:44 -08006373static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006374{
6375 struct cmd_lookup match = { NULL, hdev };
6376
6377 BT_DBG("status 0x%02x", status);
6378
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006379 if (!status) {
6380 /* Register the available SMP channels (BR/EDR and LE) only
6381 * when successfully powering on the controller. This late
6382 * registration is required so that LE SMP can clearly
6383 * decide if the public address or static address is used.
6384 */
6385 smp_register(hdev);
6386 }
6387
Johan Hedberg229ab392013-03-15 17:06:53 -05006388 hci_dev_lock(hdev);
6389
6390 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6391
6392 new_settings(hdev, match.sk);
6393
6394 hci_dev_unlock(hdev);
6395
6396 if (match.sk)
6397 sock_put(match.sk);
6398}
6399
Johan Hedberg70da6242013-03-15 17:06:51 -05006400static int powered_update_hci(struct hci_dev *hdev)
6401{
Johan Hedberg890ea892013-03-15 17:06:52 -05006402 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006403 u8 link_sec;
6404
Johan Hedberg890ea892013-03-15 17:06:52 -05006405 hci_req_init(&req, hdev);
6406
Johan Hedberg70da6242013-03-15 17:06:51 -05006407 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6408 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006409 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006410
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006411 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006412
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006413 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6414 u8 support = 0x01;
6415
6416 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6417 sizeof(support), &support);
6418 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006419 }
6420
Johan Hedbergc73eee92013-04-19 18:35:21 +03006421 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6422 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006423 struct hci_cp_write_le_host_supported cp;
6424
Marcel Holtmann32226e42014-07-24 20:04:16 +02006425 cp.le = 0x01;
6426 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006427
6428 /* Check first if we already have the right
6429 * host state (host features set)
6430 */
6431 if (cp.le != lmp_host_le_capable(hdev) ||
6432 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006433 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6434 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006435 }
6436
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006437 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006438 /* Make sure the controller has a good default for
6439 * advertising data. This also applies to the case
6440 * where BR/EDR was toggled during the AUTO_OFF phase.
6441 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006442 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006443 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006444 update_scan_rsp_data(&req);
6445 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006446
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006447 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6448 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006449
6450 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006451 }
6452
Johan Hedberg70da6242013-03-15 17:06:51 -05006453 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6454 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006455 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6456 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006457
6458 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006459 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006460 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006461 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006462 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006463 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006464 }
6465
Johan Hedberg229ab392013-03-15 17:06:53 -05006466 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006467}
6468
Johan Hedberg744cf192011-11-08 20:40:14 +02006469int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006470{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006471 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006472 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006473 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006474
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006475 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6476 return 0;
6477
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006478 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006479 if (powered_update_hci(hdev) == 0)
6480 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006481
Johan Hedberg229ab392013-03-15 17:06:53 -05006482 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6483 &match);
6484 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006485 }
6486
Johan Hedberg229ab392013-03-15 17:06:53 -05006487 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006488
6489 /* If the power off is because of hdev unregistration let
6490 * use the appropriate INVALID_INDEX status. Otherwise use
6491 * NOT_POWERED. We cover both scenarios here since later in
6492 * mgmt_index_removed() any hci_conn callbacks will have already
6493 * been triggered, potentially causing misleading DISCONNECTED
6494 * status responses.
6495 */
6496 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6497 status = MGMT_STATUS_INVALID_INDEX;
6498 else
6499 status = MGMT_STATUS_NOT_POWERED;
6500
6501 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006502
6503 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6504 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6505 zero_cod, sizeof(zero_cod), NULL);
6506
6507new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006508 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006509
6510 if (match.sk)
6511 sock_put(match.sk);
6512
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006513 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006514}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006515
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006516void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006517{
6518 struct pending_cmd *cmd;
6519 u8 status;
6520
6521 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6522 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006523 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006524
6525 if (err == -ERFKILL)
6526 status = MGMT_STATUS_RFKILLED;
6527 else
6528 status = MGMT_STATUS_FAILED;
6529
Johan Hedberga69e8372015-03-06 21:08:53 +02006530 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006531
6532 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006533}
6534
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006535void mgmt_discoverable_timeout(struct hci_dev *hdev)
6536{
6537 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006538
6539 hci_dev_lock(hdev);
6540
6541 /* When discoverable timeout triggers, then just make sure
6542 * the limited discoverable flag is cleared. Even in the case
6543 * of a timeout triggered from general discoverable, it is
6544 * safe to unconditionally clear the flag.
6545 */
6546 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006547 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006548
6549 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006550 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6551 u8 scan = SCAN_PAGE;
6552 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6553 sizeof(scan), &scan);
6554 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006555 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006556 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006557 hci_req_run(&req, NULL);
6558
6559 hdev->discov_timeout = 0;
6560
Johan Hedberg9a43e252013-10-20 19:00:07 +03006561 new_settings(hdev, NULL);
6562
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006563 hci_dev_unlock(hdev);
6564}
6565
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006566void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6567 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006568{
Johan Hedberg86742e12011-11-07 23:13:38 +02006569 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006570
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006571 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006572
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006573 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006574 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006575 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006576 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006577 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006578 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006579
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006580 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006581}
Johan Hedbergf7520542011-01-20 12:34:39 +02006582
Johan Hedbergd7b25452014-05-23 13:19:53 +03006583static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6584{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006585 switch (ltk->type) {
6586 case SMP_LTK:
6587 case SMP_LTK_SLAVE:
6588 if (ltk->authenticated)
6589 return MGMT_LTK_AUTHENTICATED;
6590 return MGMT_LTK_UNAUTHENTICATED;
6591 case SMP_LTK_P256:
6592 if (ltk->authenticated)
6593 return MGMT_LTK_P256_AUTH;
6594 return MGMT_LTK_P256_UNAUTH;
6595 case SMP_LTK_P256_DEBUG:
6596 return MGMT_LTK_P256_DEBUG;
6597 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006598
6599 return MGMT_LTK_UNAUTHENTICATED;
6600}
6601
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006602void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006603{
6604 struct mgmt_ev_new_long_term_key ev;
6605
6606 memset(&ev, 0, sizeof(ev));
6607
Marcel Holtmann5192d302014-02-19 17:11:58 -08006608 /* Devices using resolvable or non-resolvable random addresses
6609 * without providing an indentity resolving key don't require
6610 * to store long term keys. Their addresses will change the
6611 * next time around.
6612 *
6613 * Only when a remote device provides an identity address
6614 * make sure the long term key is stored. If the remote
6615 * identity is known, the long term keys are internally
6616 * mapped to the identity address. So allow static random
6617 * and public addresses here.
6618 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006619 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6620 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6621 ev.store_hint = 0x00;
6622 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006623 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006624
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006625 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006626 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006627 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006628 ev.key.enc_size = key->enc_size;
6629 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006630 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006631
Johan Hedberg2ceba532014-06-16 19:25:16 +03006632 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006633 ev.key.master = 1;
6634
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006635 memcpy(ev.key.val, key->val, sizeof(key->val));
6636
Marcel Holtmann083368f2013-10-15 14:26:29 -07006637 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006638}
6639
Johan Hedberg95fbac82014-02-19 15:18:31 +02006640void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6641{
6642 struct mgmt_ev_new_irk ev;
6643
6644 memset(&ev, 0, sizeof(ev));
6645
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006646 /* For identity resolving keys from devices that are already
6647 * using a public address or static random address, do not
6648 * ask for storing this key. The identity resolving key really
6649 * is only mandatory for devices using resovlable random
6650 * addresses.
6651 *
6652 * Storing all identity resolving keys has the downside that
6653 * they will be also loaded on next boot of they system. More
6654 * identity resolving keys, means more time during scanning is
6655 * needed to actually resolve these addresses.
6656 */
6657 if (bacmp(&irk->rpa, BDADDR_ANY))
6658 ev.store_hint = 0x01;
6659 else
6660 ev.store_hint = 0x00;
6661
Johan Hedberg95fbac82014-02-19 15:18:31 +02006662 bacpy(&ev.rpa, &irk->rpa);
6663 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6664 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6665 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6666
6667 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6668}
6669
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006670void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6671 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006672{
6673 struct mgmt_ev_new_csrk ev;
6674
6675 memset(&ev, 0, sizeof(ev));
6676
6677 /* Devices using resolvable or non-resolvable random addresses
6678 * without providing an indentity resolving key don't require
6679 * to store signature resolving keys. Their addresses will change
6680 * the next time around.
6681 *
6682 * Only when a remote device provides an identity address
6683 * make sure the signature resolving key is stored. So allow
6684 * static random and public addresses here.
6685 */
6686 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6687 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6688 ev.store_hint = 0x00;
6689 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006690 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006691
6692 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6693 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006694 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006695 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6696
6697 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6698}
6699
Andre Guedesffb5a8272014-07-01 18:10:11 -03006700void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006701 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6702 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006703{
6704 struct mgmt_ev_new_conn_param ev;
6705
Johan Hedbergc103aea2014-07-02 17:37:34 +03006706 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6707 return;
6708
Andre Guedesffb5a8272014-07-01 18:10:11 -03006709 memset(&ev, 0, sizeof(ev));
6710 bacpy(&ev.addr.bdaddr, bdaddr);
6711 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006712 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006713 ev.min_interval = cpu_to_le16(min_interval);
6714 ev.max_interval = cpu_to_le16(max_interval);
6715 ev.latency = cpu_to_le16(latency);
6716 ev.timeout = cpu_to_le16(timeout);
6717
6718 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6719}
6720
Marcel Holtmann94933992013-10-15 10:26:39 -07006721static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6722 u8 data_len)
6723{
6724 eir[eir_len++] = sizeof(type) + data_len;
6725 eir[eir_len++] = type;
6726 memcpy(&eir[eir_len], data, data_len);
6727 eir_len += data_len;
6728
6729 return eir_len;
6730}
6731
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006732void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6733 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006734{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006735 char buf[512];
6736 struct mgmt_ev_device_connected *ev = (void *) buf;
6737 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006738
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006739 bacpy(&ev->addr.bdaddr, &conn->dst);
6740 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006741
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006742 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006743
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006744 /* We must ensure that the EIR Data fields are ordered and
6745 * unique. Keep it simple for now and avoid the problem by not
6746 * adding any BR/EDR data to the LE adv.
6747 */
6748 if (conn->le_adv_data_len > 0) {
6749 memcpy(&ev->eir[eir_len],
6750 conn->le_adv_data, conn->le_adv_data_len);
6751 eir_len = conn->le_adv_data_len;
6752 } else {
6753 if (name_len > 0)
6754 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6755 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006756
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006757 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006758 eir_len = eir_append_data(ev->eir, eir_len,
6759 EIR_CLASS_OF_DEV,
6760 conn->dev_class, 3);
6761 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006762
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006763 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006764
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006765 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6766 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006767}
6768
Johan Hedberg8962ee72011-01-20 12:40:27 +02006769static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6770{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006771 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006772
Johan Hedbergf5818c22014-12-05 13:36:02 +02006773 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006774
6775 *sk = cmd->sk;
6776 sock_hold(*sk);
6777
Johan Hedberga664b5b2011-02-19 12:06:02 -03006778 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006779}
6780
Johan Hedberg124f6e32012-02-09 13:50:12 +02006781static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006782{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006783 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006784 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006785
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006786 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6787
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006788 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006789 mgmt_pending_remove(cmd);
6790}
6791
Johan Hedberg84c61d92014-08-01 11:13:30 +03006792bool mgmt_powering_down(struct hci_dev *hdev)
6793{
6794 struct pending_cmd *cmd;
6795 struct mgmt_mode *cp;
6796
6797 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6798 if (!cmd)
6799 return false;
6800
6801 cp = cmd->param;
6802 if (!cp->val)
6803 return true;
6804
6805 return false;
6806}
6807
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006808void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006809 u8 link_type, u8 addr_type, u8 reason,
6810 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006811{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006812 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006813 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006814
Johan Hedberg84c61d92014-08-01 11:13:30 +03006815 /* The connection is still in hci_conn_hash so test for 1
6816 * instead of 0 to know if this is the last one.
6817 */
6818 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6819 cancel_delayed_work(&hdev->power_off);
6820 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006821 }
6822
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006823 if (!mgmt_connected)
6824 return;
6825
Andre Guedes57eb7762013-10-30 19:01:41 -03006826 if (link_type != ACL_LINK && link_type != LE_LINK)
6827 return;
6828
Johan Hedberg744cf192011-11-08 20:40:14 +02006829 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006830
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006831 bacpy(&ev.addr.bdaddr, bdaddr);
6832 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6833 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006834
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006835 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006836
6837 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006838 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006839
Johan Hedberg124f6e32012-02-09 13:50:12 +02006840 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006841 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006842}
6843
Marcel Holtmann78929242013-10-06 23:55:47 -07006844void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6845 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006846{
Andre Guedes3655bba2013-10-30 19:01:40 -03006847 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6848 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006849 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006850
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006851 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6852 hdev);
6853
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006854 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006855 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006856 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006857
Andre Guedes3655bba2013-10-30 19:01:40 -03006858 cp = cmd->param;
6859
6860 if (bacmp(bdaddr, &cp->addr.bdaddr))
6861 return;
6862
6863 if (cp->addr.type != bdaddr_type)
6864 return;
6865
Johan Hedbergf5818c22014-12-05 13:36:02 +02006866 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006867 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006868}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006869
Marcel Holtmann445608d2013-10-06 23:55:48 -07006870void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6871 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006872{
6873 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006874
Johan Hedberg84c61d92014-08-01 11:13:30 +03006875 /* The connection is still in hci_conn_hash so test for 1
6876 * instead of 0 to know if this is the last one.
6877 */
6878 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6879 cancel_delayed_work(&hdev->power_off);
6880 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006881 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006882
Johan Hedberg4c659c32011-11-07 23:13:39 +02006883 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006884 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006885 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006886
Marcel Holtmann445608d2013-10-06 23:55:48 -07006887 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006888}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006889
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006890void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006891{
6892 struct mgmt_ev_pin_code_request ev;
6893
Johan Hedbergd8457692012-02-17 14:24:57 +02006894 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006895 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006896 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006897
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006898 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006899}
6900
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006901void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6902 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006903{
6904 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006905
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006906 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006907 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006908 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006909
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006910 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006911 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006912}
6913
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006914void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6915 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006916{
6917 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006918
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006919 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006920 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006921 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006922
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006923 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006924 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006925}
Johan Hedberga5c29682011-02-19 12:05:57 -03006926
Johan Hedberg744cf192011-11-08 20:40:14 +02006927int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006928 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006929 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006930{
6931 struct mgmt_ev_user_confirm_request ev;
6932
Johan Hedberg744cf192011-11-08 20:40:14 +02006933 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006934
Johan Hedberg272d90d2012-02-09 15:26:12 +02006935 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006936 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006937 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006938 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006939
Johan Hedberg744cf192011-11-08 20:40:14 +02006940 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006941 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006942}
6943
Johan Hedberg272d90d2012-02-09 15:26:12 +02006944int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006945 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006946{
6947 struct mgmt_ev_user_passkey_request ev;
6948
6949 BT_DBG("%s", hdev->name);
6950
Johan Hedberg272d90d2012-02-09 15:26:12 +02006951 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006952 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006953
6954 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006955 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006956}
6957
Brian Gix0df4c182011-11-16 13:53:13 -08006958static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006959 u8 link_type, u8 addr_type, u8 status,
6960 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006961{
6962 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006963
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006964 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006965 if (!cmd)
6966 return -ENOENT;
6967
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006968 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006969 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006970
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006971 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006972}
6973
Johan Hedberg744cf192011-11-08 20:40:14 +02006974int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006975 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006976{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006977 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006978 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006979}
6980
Johan Hedberg272d90d2012-02-09 15:26:12 +02006981int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006982 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006983{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006984 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006985 status,
6986 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006987}
Johan Hedberg2a611692011-02-19 12:06:00 -03006988
Brian Gix604086b2011-11-23 08:28:33 -08006989int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006990 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006991{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006992 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006993 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006994}
6995
Johan Hedberg272d90d2012-02-09 15:26:12 +02006996int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006997 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006998{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006999 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007000 status,
7001 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007002}
7003
Johan Hedberg92a25252012-09-06 18:39:26 +03007004int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7005 u8 link_type, u8 addr_type, u32 passkey,
7006 u8 entered)
7007{
7008 struct mgmt_ev_passkey_notify ev;
7009
7010 BT_DBG("%s", hdev->name);
7011
7012 bacpy(&ev.addr.bdaddr, bdaddr);
7013 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7014 ev.passkey = __cpu_to_le32(passkey);
7015 ev.entered = entered;
7016
7017 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7018}
7019
Johan Hedberge1e930f2014-09-08 17:09:49 -07007020void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007021{
7022 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007023 struct pending_cmd *cmd;
7024 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007025
Johan Hedberge1e930f2014-09-08 17:09:49 -07007026 bacpy(&ev.addr.bdaddr, &conn->dst);
7027 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7028 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007029
Johan Hedberge1e930f2014-09-08 17:09:49 -07007030 cmd = find_pairing(conn);
7031
7032 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7033 cmd ? cmd->sk : NULL);
7034
Johan Hedberga511b352014-12-11 21:45:45 +02007035 if (cmd) {
7036 cmd->cmd_complete(cmd, status);
7037 mgmt_pending_remove(cmd);
7038 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007039}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007040
Marcel Holtmann464996a2013-10-15 14:26:24 -07007041void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007042{
7043 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007044 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007045
7046 if (status) {
7047 u8 mgmt_err = mgmt_status(status);
7048 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007049 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007050 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007051 }
7052
Marcel Holtmann464996a2013-10-15 14:26:24 -07007053 if (test_bit(HCI_AUTH, &hdev->flags))
7054 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7055 &hdev->dev_flags);
7056 else
7057 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7058 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007059
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007060 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007061 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007062
Johan Hedberg47990ea2012-02-22 11:58:37 +02007063 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007064 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007065
7066 if (match.sk)
7067 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007068}
7069
Johan Hedberg890ea892013-03-15 17:06:52 -05007070static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007071{
Johan Hedberg890ea892013-03-15 17:06:52 -05007072 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007073 struct hci_cp_write_eir cp;
7074
Johan Hedberg976eb202012-10-24 21:12:01 +03007075 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007076 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007077
Johan Hedbergc80da272012-02-22 15:38:48 +02007078 memset(hdev->eir, 0, sizeof(hdev->eir));
7079
Johan Hedbergcacaf522012-02-21 00:52:42 +02007080 memset(&cp, 0, sizeof(cp));
7081
Johan Hedberg890ea892013-03-15 17:06:52 -05007082 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007083}
7084
Marcel Holtmann3e248562013-10-15 14:26:25 -07007085void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007086{
7087 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007088 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007089 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007090
7091 if (status) {
7092 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007093
7094 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007095 &hdev->dev_flags)) {
7096 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007097 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007098 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007099
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007100 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7101 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007102 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007103 }
7104
7105 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007106 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007107 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007108 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7109 if (!changed)
7110 changed = test_and_clear_bit(HCI_HS_ENABLED,
7111 &hdev->dev_flags);
7112 else
7113 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007114 }
7115
7116 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7117
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007118 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007119 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007120
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007121 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007122 sock_put(match.sk);
7123
Johan Hedberg890ea892013-03-15 17:06:52 -05007124 hci_req_init(&req, hdev);
7125
Johan Hedberg37699722014-06-24 14:00:27 +03007126 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
7127 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
7128 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7129 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007130 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007131 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007132 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007133 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007134
7135 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007136}
7137
Johan Hedberg92da6092013-03-15 17:06:55 -05007138static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007139{
7140 struct cmd_lookup *match = data;
7141
Johan Hedberg90e70452012-02-23 23:09:40 +02007142 if (match->sk == NULL) {
7143 match->sk = cmd->sk;
7144 sock_hold(match->sk);
7145 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007146}
7147
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007148void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7149 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007150{
Johan Hedberg90e70452012-02-23 23:09:40 +02007151 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007152
Johan Hedberg92da6092013-03-15 17:06:55 -05007153 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7154 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7155 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007156
7157 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007158 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7159 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007160
7161 if (match.sk)
7162 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007163}
7164
Marcel Holtmann7667da32013-10-15 14:26:27 -07007165void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007166{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007167 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05007168 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007169
Johan Hedberg13928972013-03-15 17:07:00 -05007170 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007171 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007172
7173 memset(&ev, 0, sizeof(ev));
7174 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007175 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007176
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007177 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007178 if (!cmd) {
7179 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007180
Johan Hedberg13928972013-03-15 17:07:00 -05007181 /* If this is a HCI command related to powering on the
7182 * HCI dev don't send any mgmt signals.
7183 */
7184 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007185 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007186 }
7187
Marcel Holtmann7667da32013-10-15 14:26:27 -07007188 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7189 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007190}
Szymon Jancc35938b2011-03-22 13:12:21 +01007191
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007192void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007193 u8 *rand192, u8 *hash256, u8 *rand256,
7194 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007195{
7196 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007197
Johan Hedberg744cf192011-11-08 20:40:14 +02007198 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007199
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007200 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007201 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007202 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007203
7204 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007205 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7206 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007207 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007208 struct mgmt_rp_read_local_oob_data rp;
7209 size_t rp_size = sizeof(rp);
7210
7211 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7212 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7213
Johan Hedberg710f11c2014-05-26 11:21:22 +03007214 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007215 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007216 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007217 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007218 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007219 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007220
7221 cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7222 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007223 }
7224
7225 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007226}
Johan Hedberge17acd42011-03-30 23:57:16 +03007227
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007228static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7229{
7230 int i;
7231
7232 for (i = 0; i < uuid_count; i++) {
7233 if (!memcmp(uuid, uuids[i], 16))
7234 return true;
7235 }
7236
7237 return false;
7238}
7239
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007240static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7241{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007242 u16 parsed = 0;
7243
7244 while (parsed < eir_len) {
7245 u8 field_len = eir[0];
7246 u8 uuid[16];
7247 int i;
7248
7249 if (field_len == 0)
7250 break;
7251
7252 if (eir_len - parsed < field_len + 1)
7253 break;
7254
7255 switch (eir[1]) {
7256 case EIR_UUID16_ALL:
7257 case EIR_UUID16_SOME:
7258 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007259 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007260 uuid[13] = eir[i + 3];
7261 uuid[12] = eir[i + 2];
7262 if (has_uuid(uuid, uuid_count, uuids))
7263 return true;
7264 }
7265 break;
7266 case EIR_UUID32_ALL:
7267 case EIR_UUID32_SOME:
7268 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007269 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007270 uuid[15] = eir[i + 5];
7271 uuid[14] = eir[i + 4];
7272 uuid[13] = eir[i + 3];
7273 uuid[12] = eir[i + 2];
7274 if (has_uuid(uuid, uuid_count, uuids))
7275 return true;
7276 }
7277 break;
7278 case EIR_UUID128_ALL:
7279 case EIR_UUID128_SOME:
7280 for (i = 0; i + 17 <= field_len; i += 16) {
7281 memcpy(uuid, eir + i + 2, 16);
7282 if (has_uuid(uuid, uuid_count, uuids))
7283 return true;
7284 }
7285 break;
7286 }
7287
7288 parsed += field_len + 1;
7289 eir += field_len + 1;
7290 }
7291
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007292 return false;
7293}
7294
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007295static void restart_le_scan(struct hci_dev *hdev)
7296{
7297 /* If controller is not scanning we are done. */
7298 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7299 return;
7300
7301 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7302 hdev->discovery.scan_start +
7303 hdev->discovery.scan_duration))
7304 return;
7305
7306 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7307 DISCOV_LE_RESTART_DELAY);
7308}
7309
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007310static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7311 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7312{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007313 /* If a RSSI threshold has been specified, and
7314 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7315 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7316 * is set, let it through for further processing, as we might need to
7317 * restart the scan.
7318 *
7319 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7320 * the results are also dropped.
7321 */
7322 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7323 (rssi == HCI_RSSI_INVALID ||
7324 (rssi < hdev->discovery.rssi &&
7325 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7326 return false;
7327
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007328 if (hdev->discovery.uuid_count != 0) {
7329 /* If a list of UUIDs is provided in filter, results with no
7330 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007331 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007332 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7333 hdev->discovery.uuids) &&
7334 !eir_has_uuids(scan_rsp, scan_rsp_len,
7335 hdev->discovery.uuid_count,
7336 hdev->discovery.uuids))
7337 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007338 }
7339
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007340 /* If duplicate filtering does not report RSSI changes, then restart
7341 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007342 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007343 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7344 restart_le_scan(hdev);
7345
7346 /* Validate RSSI value against the RSSI threshold once more. */
7347 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7348 rssi < hdev->discovery.rssi)
7349 return false;
7350 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007351
7352 return true;
7353}
7354
Marcel Holtmann901801b2013-10-06 23:55:51 -07007355void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007356 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7357 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007358{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007359 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007360 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007361 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007362
Johan Hedberg75ce2082014-07-02 22:42:01 +03007363 /* Don't send events for a non-kernel initiated discovery. With
7364 * LE one exception is if we have pend_le_reports > 0 in which
7365 * case we're doing passive scanning and want these events.
7366 */
7367 if (!hci_discovery_active(hdev)) {
7368 if (link_type == ACL_LINK)
7369 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007370 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007371 return;
7372 }
Andre Guedes12602d02013-04-30 15:29:40 -03007373
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007374 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007375 /* We are using service discovery */
7376 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7377 scan_rsp_len))
7378 return;
7379 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007380
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007381 /* Make sure that the buffer is big enough. The 5 extra bytes
7382 * are for the potential CoD field.
7383 */
7384 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007385 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007386
Johan Hedberg1dc06092012-01-15 21:01:23 +02007387 memset(buf, 0, sizeof(buf));
7388
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007389 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7390 * RSSI value was reported as 0 when not available. This behavior
7391 * is kept when using device discovery. This is required for full
7392 * backwards compatibility with the API.
7393 *
7394 * However when using service discovery, the value 127 will be
7395 * returned when the RSSI is not available.
7396 */
Szymon Janc91200e92015-01-22 16:57:05 +01007397 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7398 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007399 rssi = 0;
7400
Johan Hedberg841c5642014-07-07 12:45:54 +03007401 bacpy(&ev->addr.bdaddr, bdaddr);
7402 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007403 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007404 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007405
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007406 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007407 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007408 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007409
Johan Hedberg1dc06092012-01-15 21:01:23 +02007410 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7411 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007412 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007413
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007414 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007415 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007416 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007417
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007418 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7419 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007420
Marcel Holtmann901801b2013-10-06 23:55:51 -07007421 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007422}
Johan Hedberga88a9652011-03-30 13:18:12 +03007423
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007424void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7425 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007426{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007427 struct mgmt_ev_device_found *ev;
7428 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7429 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007430
Johan Hedbergb644ba32012-01-17 21:48:47 +02007431 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007432
Johan Hedbergb644ba32012-01-17 21:48:47 +02007433 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007434
Johan Hedbergb644ba32012-01-17 21:48:47 +02007435 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007436 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007437 ev->rssi = rssi;
7438
7439 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007440 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007441
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007442 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007443
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007444 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007445}
Johan Hedberg314b2382011-04-27 10:29:57 -04007446
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007447void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007448{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007449 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007450
Andre Guedes343fb142011-11-22 17:14:19 -03007451 BT_DBG("%s discovering %u", hdev->name, discovering);
7452
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007453 memset(&ev, 0, sizeof(ev));
7454 ev.type = hdev->discovery.type;
7455 ev.discovering = discovering;
7456
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007457 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007458}
Antti Julku5e762442011-08-25 16:48:02 +03007459
Marcel Holtmann1904a852015-01-11 13:50:44 -08007460static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007461{
7462 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007463}
7464
7465void mgmt_reenable_advertising(struct hci_dev *hdev)
7466{
7467 struct hci_request req;
7468
Marcel Holtmann5976e602013-10-06 04:08:14 -07007469 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7470 return;
7471
7472 hci_req_init(&req, hdev);
7473 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007474 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007475}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007476
7477static struct hci_mgmt_chan chan = {
7478 .channel = HCI_CHANNEL_CONTROL,
7479 .handler_count = ARRAY_SIZE(mgmt_handlers),
7480 .handlers = mgmt_handlers,
7481};
7482
7483int mgmt_init(void)
7484{
7485 return hci_mgmt_chan_register(&chan);
7486}
7487
7488void mgmt_exit(void)
7489{
7490 hci_mgmt_chan_unregister(&chan);
7491}