blob: d185a980098336de121fadb8964a15d6143b1531 [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
Szymon Janc4e51eae2011-02-25 19:05:48 +0100252static int 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)
1399 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1400 MGMT_STATUS_INVALID_PARAMS);
1401
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)) {
1405 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1406 MGMT_STATUS_BUSY);
1407 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
1495 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1496 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);
1563 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 Hedberg33c525c2012-10-24 21:11:58 +03001619 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001620 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 Hedberga7e80f22013-01-09 16:05:19 +02001623 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1624 MGMT_STATUS_INVALID_PARAMS);
1625
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 Hedbergbdb6d972012-02-28 06:13:32 +02001633 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001634 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 Hedbergbdb6d972012-02-28 06:13:32 +02001639 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001640 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 Hedbergbdb6d972012-02-28 06:13:32 +02001646 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001647 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 Hedbergbdb6d972012-02-28 06:13:32 +02001652 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001653 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);
1822 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1823 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 Hedberg33c525c2012-10-24 21:11:58 +03001897 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001898 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)
1901 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1902 MGMT_STATUS_INVALID_PARAMS);
1903
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 Hedbergbdb6d972012-02-28 06:13:32 +02001913 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001914 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 Hedbergb2939472014-07-30 09:22:23 +03001999 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02002000 MGMT_STATUS_INVALID_PARAMS);
2001
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 Hedberg33c525c2012-10-24 21:11:58 +03002033 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002034 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002035
Johan Hedberga7e80f22013-01-09 16:05:19 +02002036 if (cp->val != 0x00 && cp->val != 0x01)
2037 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2038 MGMT_STATUS_INVALID_PARAMS);
2039
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 Hedbergbdb6d972012-02-28 06:13:32 +02002062 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002063 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)
2102 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2103
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002104 if (!lmp_ssp_capable(hdev))
2105 return 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)
2109 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2110 MGMT_STATUS_INVALID_PARAMS);
2111
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)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002141 err = 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)
2183 return 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))
2186 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2187 MGMT_STATUS_NOT_SUPPORTED);
2188
2189 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2190 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2191 MGMT_STATUS_REJECTED);
2192
Johan Hedberga7e80f22013-01-09 16:05:19 +02002193 if (cp->val != 0x00 && cp->val != 0x01)
2194 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2195 MGMT_STATUS_INVALID_PARAMS);
2196
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)) {
2200 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2201 MGMT_STATUS_BUSY);
2202 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)) {
2209 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2210 MGMT_STATUS_REJECTED);
2211 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))
2281 return 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)
2285 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2286 MGMT_STATUS_INVALID_PARAMS);
2287
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 Hedbergc73eee92013-04-19 18:35:21 +03002290 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2291 MGMT_STATUS_REJECTED);
2292
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 Hedbergbdb6d972012-02-28 06:13:32 +02002323 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002324 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 Hedbergbdb6d972012-02-28 06:13:32 +02002439 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002440 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 Hedbergbdb6d972012-02-28 06:13:32 +02002520 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002521 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 Hedbergbdb6d972012-02-28 06:13:32 +02002549 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002550 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 Hedberg13ecd8b2013-01-09 15:29:38 +02002601 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2602 MGMT_STATUS_NOT_SUPPORTED);
2603
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)) {
2607 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2608 MGMT_STATUS_BUSY);
2609 goto unlock;
2610 }
2611
2612 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2613 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2614 MGMT_STATUS_INVALID_PARAMS);
2615 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))
2674 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2675 MGMT_STATUS_NOT_SUPPORTED);
2676
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);
2681 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2682 MGMT_STATUS_INVALID_PARAMS);
2683 }
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 Hedbergbdb6d972012-02-28 06:13:32 +02002690 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002691 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)
2695 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2696 MGMT_STATUS_INVALID_PARAMS);
2697
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 Hedberg4ee71b22013-01-20 14:27:19 +02002705 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2706 MGMT_STATUS_INVALID_PARAMS);
2707 }
2708
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002709 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710
2711 hci_link_keys_clear(hdev);
2712
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002713 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002714 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2715 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002716 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002717 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2718 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002719
2720 if (changed)
2721 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002722
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002723 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002724 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002725
Johan Hedberg58e92932014-06-24 14:00:26 +03002726 /* Always ignore debug keys and require a new pairing if
2727 * the user wants to use them.
2728 */
2729 if (key->type == HCI_LK_DEBUG_COMBINATION)
2730 continue;
2731
Johan Hedberg7652ff62014-06-24 13:15:49 +03002732 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2733 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002734 }
2735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002736 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002737
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002738 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002739
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002740 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002741}
2742
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002743static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002744 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002745{
2746 struct mgmt_ev_device_unpaired ev;
2747
2748 bacpy(&ev.addr.bdaddr, bdaddr);
2749 ev.addr.type = addr_type;
2750
2751 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002752 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002753}
2754
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002757{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002758 struct mgmt_cp_unpair_device *cp = data;
2759 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002760 struct hci_cp_disconnect dc;
2761 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002762 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002763 int err;
2764
Johan Hedberga8a1d192011-11-10 15:54:38 +02002765 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002766 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2767 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002768
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002769 if (!bdaddr_type_is_valid(cp->addr.type))
2770 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2771 MGMT_STATUS_INVALID_PARAMS,
2772 &rp, sizeof(rp));
2773
Johan Hedberg118da702013-01-20 14:27:20 +02002774 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2775 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2776 MGMT_STATUS_INVALID_PARAMS,
2777 &rp, sizeof(rp));
2778
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002779 hci_dev_lock(hdev);
2780
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002781 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002782 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002783 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002784 goto unlock;
2785 }
2786
Johan Hedberge0b2b272014-02-18 17:14:31 +02002787 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002788 /* If disconnection is requested, then look up the
2789 * connection. If the remote device is connected, it
2790 * will be later used to terminate the link.
2791 *
2792 * Setting it to NULL explicitly will cause no
2793 * termination of the link.
2794 */
2795 if (cp->disconnect)
2796 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2797 &cp->addr.bdaddr);
2798 else
2799 conn = NULL;
2800
Johan Hedberg124f6e32012-02-09 13:50:12 +02002801 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002802 } else {
2803 u8 addr_type;
2804
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002805 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2806 &cp->addr.bdaddr);
2807 if (conn) {
2808 /* Defer clearing up the connection parameters
2809 * until closing to give a chance of keeping
2810 * them if a repairing happens.
2811 */
2812 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2813
2814 /* If disconnection is not requested, then
2815 * clear the connection variable so that the
2816 * link is not terminated.
2817 */
2818 if (!cp->disconnect)
2819 conn = NULL;
2820 }
2821
Johan Hedberge0b2b272014-02-18 17:14:31 +02002822 if (cp->addr.type == BDADDR_LE_PUBLIC)
2823 addr_type = ADDR_LE_DEV_PUBLIC;
2824 else
2825 addr_type = ADDR_LE_DEV_RANDOM;
2826
Johan Hedberga7ec7332014-02-18 17:14:35 +02002827 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2828
Johan Hedberge0b2b272014-02-18 17:14:31 +02002829 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2830 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002831
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002832 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002833 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002834 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002835 goto unlock;
2836 }
2837
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002838 /* If the connection variable is set, then termination of the
2839 * link is requested.
2840 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002841 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002842 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002843 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002844 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002845 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002846 }
2847
Johan Hedberg124f6e32012-02-09 13:50:12 +02002848 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002849 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002850 if (!cmd) {
2851 err = -ENOMEM;
2852 goto unlock;
2853 }
2854
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002855 cmd->cmd_complete = addr_cmd_complete;
2856
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002857 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002858 dc.reason = 0x13; /* Remote User Terminated Connection */
2859 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2860 if (err < 0)
2861 mgmt_pending_remove(cmd);
2862
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002863unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002864 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002865 return err;
2866}
2867
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002868static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002869 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002870{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002871 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002872 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002873 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002874 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002875 int err;
2876
2877 BT_DBG("");
2878
Johan Hedberg06a63b12013-01-20 14:27:21 +02002879 memset(&rp, 0, sizeof(rp));
2880 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2881 rp.addr.type = cp->addr.type;
2882
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002883 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002884 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2885 MGMT_STATUS_INVALID_PARAMS,
2886 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002887
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002888 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002889
2890 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002891 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2892 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002893 goto failed;
2894 }
2895
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002896 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002897 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2898 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002899 goto failed;
2900 }
2901
Andre Guedes591f47f2012-04-24 21:02:49 -03002902 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002903 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2904 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002905 else
2906 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002907
Vishal Agarwalf9607272012-06-13 05:32:43 +05302908 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002909 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2910 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002911 goto failed;
2912 }
2913
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002914 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002915 if (!cmd) {
2916 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002917 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002918 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002919
Johan Hedbergf5818c22014-12-05 13:36:02 +02002920 cmd->cmd_complete = generic_cmd_complete;
2921
Johan Hedberge3f2f922014-08-18 20:33:33 +03002922 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002923 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002924 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002925
2926failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002927 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002928 return err;
2929}
2930
Andre Guedes57c14772012-04-24 21:02:50 -03002931static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002932{
2933 switch (link_type) {
2934 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002935 switch (addr_type) {
2936 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002937 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002938
Johan Hedberg48264f02011-11-09 13:58:58 +02002939 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002940 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002941 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002942 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002943
Johan Hedberg4c659c32011-11-07 23:13:39 +02002944 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002945 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002946 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002947 }
2948}
2949
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002950static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2951 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002952{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002953 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002954 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002955 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002956 int err;
2957 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002958
2959 BT_DBG("");
2960
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002961 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002962
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002963 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002964 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002965 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002966 goto unlock;
2967 }
2968
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002969 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002970 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2971 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002972 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002973 }
2974
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002975 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002976 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002977 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002978 err = -ENOMEM;
2979 goto unlock;
2980 }
2981
Johan Hedberg2784eb42011-01-21 13:56:35 +02002982 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002983 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002984 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2985 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002986 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002987 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002988 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002989 continue;
2990 i++;
2991 }
2992
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002993 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002994
Johan Hedberg4c659c32011-11-07 23:13:39 +02002995 /* Recalculate length in case of filtered SCO connections, etc */
2996 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002997
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002998 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002999 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003000
Johan Hedberga38528f2011-01-22 06:46:43 +02003001 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003002
3003unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003004 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003005 return err;
3006}
3007
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003008static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003009 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003010{
3011 struct pending_cmd *cmd;
3012 int err;
3013
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003014 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003015 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003016 if (!cmd)
3017 return -ENOMEM;
3018
Johan Hedbergd8457692012-02-17 14:24:57 +02003019 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003020 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003021 if (err < 0)
3022 mgmt_pending_remove(cmd);
3023
3024 return err;
3025}
3026
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003027static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003028 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003029{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003030 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003031 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003032 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003033 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003034 int err;
3035
3036 BT_DBG("");
3037
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003038 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003039
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003040 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003041 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003042 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003043 goto failed;
3044 }
3045
Johan Hedbergd8457692012-02-17 14:24:57 +02003046 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003047 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003048 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003049 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003050 goto failed;
3051 }
3052
3053 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003054 struct mgmt_cp_pin_code_neg_reply ncp;
3055
3056 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003057
3058 BT_ERR("PIN code is not 16 bytes long");
3059
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003060 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003061 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003062 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003063 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003064
3065 goto failed;
3066 }
3067
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003068 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003069 if (!cmd) {
3070 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003071 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003072 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003073
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003074 cmd->cmd_complete = addr_cmd_complete;
3075
Johan Hedbergd8457692012-02-17 14:24:57 +02003076 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003077 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003078 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003079
3080 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3081 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003082 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003083
3084failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003085 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003086 return err;
3087}
3088
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003089static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3090 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003091{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003092 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003093
3094 BT_DBG("");
3095
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003096 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3097 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3098 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3099
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003100 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003101
3102 hdev->io_capability = cp->io_capability;
3103
3104 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003105 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003106
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003107 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003108
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003109 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3110 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003111}
3112
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003113static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003114{
3115 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003116 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003117
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003118 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003119 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3120 continue;
3121
Johan Hedberge9a416b2011-02-19 12:05:56 -03003122 if (cmd->user_data != conn)
3123 continue;
3124
3125 return cmd;
3126 }
3127
3128 return NULL;
3129}
3130
Johan Hedberg9df74652014-12-19 22:26:03 +02003131static int pairing_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003132{
3133 struct mgmt_rp_pair_device rp;
3134 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003135 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003136
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003137 bacpy(&rp.addr.bdaddr, &conn->dst);
3138 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003139
Johan Hedberg9df74652014-12-19 22:26:03 +02003140 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
3141 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003142
3143 /* So we don't get further callbacks for this connection */
3144 conn->connect_cfm_cb = NULL;
3145 conn->security_cfm_cb = NULL;
3146 conn->disconn_cfm_cb = NULL;
3147
David Herrmann76a68ba2013-04-06 20:28:37 +02003148 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003149
3150 /* The device is paired so there is no need to remove
3151 * its connection parameters anymore.
3152 */
3153 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003154
3155 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003156
3157 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003158}
3159
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003160void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3161{
3162 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3163 struct pending_cmd *cmd;
3164
3165 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003166 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003167 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003168 mgmt_pending_remove(cmd);
3169 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003170}
3171
Johan Hedberge9a416b2011-02-19 12:05:56 -03003172static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3173{
3174 struct pending_cmd *cmd;
3175
3176 BT_DBG("status %u", status);
3177
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003178 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003179 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003180 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003181 return;
3182 }
3183
3184 cmd->cmd_complete(cmd, mgmt_status(status));
3185 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003186}
3187
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003188static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303189{
3190 struct pending_cmd *cmd;
3191
3192 BT_DBG("status %u", status);
3193
3194 if (!status)
3195 return;
3196
3197 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003198 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303199 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003200 return;
3201 }
3202
3203 cmd->cmd_complete(cmd, mgmt_status(status));
3204 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303205}
3206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003207static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003208 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003209{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003210 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003211 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003212 struct pending_cmd *cmd;
3213 u8 sec_level, auth_type;
3214 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003215 int err;
3216
3217 BT_DBG("");
3218
Szymon Jancf950a30e2013-01-18 12:48:07 +01003219 memset(&rp, 0, sizeof(rp));
3220 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3221 rp.addr.type = cp->addr.type;
3222
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003223 if (!bdaddr_type_is_valid(cp->addr.type))
3224 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3225 MGMT_STATUS_INVALID_PARAMS,
3226 &rp, sizeof(rp));
3227
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003228 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3229 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3230 MGMT_STATUS_INVALID_PARAMS,
3231 &rp, sizeof(rp));
3232
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003233 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003234
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003235 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003236 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3237 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003238 goto unlock;
3239 }
3240
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003241 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003242 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003243
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003244 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003245 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3246 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003247 } else {
3248 u8 addr_type;
3249
3250 /* Convert from L2CAP channel address type to HCI address type
3251 */
3252 if (cp->addr.type == BDADDR_LE_PUBLIC)
3253 addr_type = ADDR_LE_DEV_PUBLIC;
3254 else
3255 addr_type = ADDR_LE_DEV_RANDOM;
3256
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003257 /* When pairing a new device, it is expected to remember
3258 * this device for future connections. Adding the connection
3259 * parameter information ahead of time allows tracking
3260 * of the slave preferred values and will speed up any
3261 * further connection establishment.
3262 *
3263 * If connection parameters already exist, then they
3264 * will be kept and this function does nothing.
3265 */
3266 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3267
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003268 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003269 sec_level, HCI_LE_CONN_TIMEOUT,
3270 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003271 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003272
Ville Tervo30e76272011-02-22 16:10:53 -03003273 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003274 int status;
3275
3276 if (PTR_ERR(conn) == -EBUSY)
3277 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003278 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3279 status = MGMT_STATUS_NOT_SUPPORTED;
3280 else if (PTR_ERR(conn) == -ECONNREFUSED)
3281 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003282 else
3283 status = MGMT_STATUS_CONNECT_FAILED;
3284
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003285 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003286 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003287 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003288 goto unlock;
3289 }
3290
3291 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003292 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003293 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003294 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003295 goto unlock;
3296 }
3297
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003298 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003299 if (!cmd) {
3300 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003301 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003302 goto unlock;
3303 }
3304
Johan Hedberg04ab2742014-12-05 13:36:04 +02003305 cmd->cmd_complete = pairing_complete;
3306
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003307 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003308 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003309 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003310 conn->security_cfm_cb = pairing_complete_cb;
3311 conn->disconn_cfm_cb = pairing_complete_cb;
3312 } else {
3313 conn->connect_cfm_cb = le_pairing_complete_cb;
3314 conn->security_cfm_cb = le_pairing_complete_cb;
3315 conn->disconn_cfm_cb = le_pairing_complete_cb;
3316 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003317
Johan Hedberge9a416b2011-02-19 12:05:56 -03003318 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003319 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003320
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003321 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003322 hci_conn_security(conn, sec_level, auth_type, true)) {
3323 cmd->cmd_complete(cmd, 0);
3324 mgmt_pending_remove(cmd);
3325 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003326
3327 err = 0;
3328
3329unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003330 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003331 return err;
3332}
3333
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003334static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3335 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003336{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003337 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003338 struct pending_cmd *cmd;
3339 struct hci_conn *conn;
3340 int err;
3341
3342 BT_DBG("");
3343
Johan Hedberg28424702012-02-02 04:02:29 +02003344 hci_dev_lock(hdev);
3345
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003346 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003347 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003348 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003349 goto unlock;
3350 }
3351
Johan Hedberg28424702012-02-02 04:02:29 +02003352 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3353 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003354 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003355 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003356 goto unlock;
3357 }
3358
3359 conn = cmd->user_data;
3360
3361 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003362 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003363 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003364 goto unlock;
3365 }
3366
Johan Hedberga511b352014-12-11 21:45:45 +02003367 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3368 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003369
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003370 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003371 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003372unlock:
3373 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003374 return err;
3375}
3376
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003377static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003378 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003379 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003380{
Johan Hedberga5c29682011-02-19 12:05:57 -03003381 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003382 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003383 int err;
3384
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003385 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003386
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003387 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003388 err = cmd_complete(sk, hdev->id, mgmt_op,
3389 MGMT_STATUS_NOT_POWERED, addr,
3390 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003391 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003392 }
3393
Johan Hedberg1707c602013-03-15 17:07:15 -05003394 if (addr->type == BDADDR_BREDR)
3395 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003396 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003397 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003398
Johan Hedberg272d90d2012-02-09 15:26:12 +02003399 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003400 err = cmd_complete(sk, hdev->id, mgmt_op,
3401 MGMT_STATUS_NOT_CONNECTED, addr,
3402 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003403 goto done;
3404 }
3405
Johan Hedberg1707c602013-03-15 17:07:15 -05003406 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003407 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003408 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003409 err = cmd_complete(sk, hdev->id, mgmt_op,
3410 MGMT_STATUS_SUCCESS, addr,
3411 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003412 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003413 err = cmd_complete(sk, hdev->id, mgmt_op,
3414 MGMT_STATUS_FAILED, addr,
3415 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003416
Brian Gix47c15e22011-11-16 13:53:14 -08003417 goto done;
3418 }
3419
Johan Hedberg1707c602013-03-15 17:07:15 -05003420 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003421 if (!cmd) {
3422 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003423 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003424 }
3425
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003426 cmd->cmd_complete = addr_cmd_complete;
3427
Brian Gix0df4c182011-11-16 13:53:13 -08003428 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003429 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3430 struct hci_cp_user_passkey_reply cp;
3431
Johan Hedberg1707c602013-03-15 17:07:15 -05003432 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003433 cp.passkey = passkey;
3434 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3435 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003436 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3437 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003438
Johan Hedberga664b5b2011-02-19 12:06:02 -03003439 if (err < 0)
3440 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003441
Brian Gix0df4c182011-11-16 13:53:13 -08003442done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003443 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003444 return err;
3445}
3446
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303447static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3448 void *data, u16 len)
3449{
3450 struct mgmt_cp_pin_code_neg_reply *cp = data;
3451
3452 BT_DBG("");
3453
Johan Hedberg1707c602013-03-15 17:07:15 -05003454 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303455 MGMT_OP_PIN_CODE_NEG_REPLY,
3456 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3457}
3458
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003459static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3460 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003461{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003462 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003463
3464 BT_DBG("");
3465
3466 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003467 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003468 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003469
Johan Hedberg1707c602013-03-15 17:07:15 -05003470 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003471 MGMT_OP_USER_CONFIRM_REPLY,
3472 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003473}
3474
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003475static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003476 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003477{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003478 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003479
3480 BT_DBG("");
3481
Johan Hedberg1707c602013-03-15 17:07:15 -05003482 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003483 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3484 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003485}
3486
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003487static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3488 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003489{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003490 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003491
3492 BT_DBG("");
3493
Johan Hedberg1707c602013-03-15 17:07:15 -05003494 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003495 MGMT_OP_USER_PASSKEY_REPLY,
3496 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003497}
3498
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003499static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003500 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003501{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003502 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003503
3504 BT_DBG("");
3505
Johan Hedberg1707c602013-03-15 17:07:15 -05003506 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003507 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3508 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003509}
3510
Johan Hedberg13928972013-03-15 17:07:00 -05003511static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003512{
Johan Hedberg13928972013-03-15 17:07:00 -05003513 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003514 struct hci_cp_write_local_name cp;
3515
Johan Hedberg13928972013-03-15 17:07:00 -05003516 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003517
Johan Hedberg890ea892013-03-15 17:06:52 -05003518 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003519}
3520
Marcel Holtmann1904a852015-01-11 13:50:44 -08003521static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003522{
3523 struct mgmt_cp_set_local_name *cp;
3524 struct pending_cmd *cmd;
3525
3526 BT_DBG("status 0x%02x", status);
3527
3528 hci_dev_lock(hdev);
3529
3530 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3531 if (!cmd)
3532 goto unlock;
3533
3534 cp = cmd->param;
3535
3536 if (status)
3537 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3538 mgmt_status(status));
3539 else
3540 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3541 cp, sizeof(*cp));
3542
3543 mgmt_pending_remove(cmd);
3544
3545unlock:
3546 hci_dev_unlock(hdev);
3547}
3548
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003549static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003550 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003551{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003552 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003553 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003554 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003555 int err;
3556
3557 BT_DBG("");
3558
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003559 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003560
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003561 /* If the old values are the same as the new ones just return a
3562 * direct command complete event.
3563 */
3564 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3565 !memcmp(hdev->short_name, cp->short_name,
3566 sizeof(hdev->short_name))) {
3567 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3568 data, len);
3569 goto failed;
3570 }
3571
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003572 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003573
Johan Hedbergb5235a62012-02-21 14:32:24 +02003574 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003575 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003576
3577 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003578 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003579 if (err < 0)
3580 goto failed;
3581
3582 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003583 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003584
Johan Hedbergb5235a62012-02-21 14:32:24 +02003585 goto failed;
3586 }
3587
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003588 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003589 if (!cmd) {
3590 err = -ENOMEM;
3591 goto failed;
3592 }
3593
Johan Hedberg13928972013-03-15 17:07:00 -05003594 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3595
Johan Hedberg890ea892013-03-15 17:06:52 -05003596 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003597
3598 if (lmp_bredr_capable(hdev)) {
3599 update_name(&req);
3600 update_eir(&req);
3601 }
3602
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003603 /* The name is stored in the scan response data and so
3604 * no need to udpate the advertising data here.
3605 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003606 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003607 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003608
Johan Hedberg13928972013-03-15 17:07:00 -05003609 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003610 if (err < 0)
3611 mgmt_pending_remove(cmd);
3612
3613failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003614 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003615 return err;
3616}
3617
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003618static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003619 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003620{
Szymon Jancc35938b2011-03-22 13:12:21 +01003621 struct pending_cmd *cmd;
3622 int err;
3623
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003624 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003625
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003626 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003627
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003628 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003629 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003630 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003631 goto unlock;
3632 }
3633
Andre Guedes9a1a1992012-07-24 15:03:48 -03003634 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003635 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003636 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003637 goto unlock;
3638 }
3639
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003640 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003641 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003642 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003643 goto unlock;
3644 }
3645
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003646 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003647 if (!cmd) {
3648 err = -ENOMEM;
3649 goto unlock;
3650 }
3651
Johan Hedberg710f11c2014-05-26 11:21:22 +03003652 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003653 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3654 0, NULL);
3655 else
3656 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3657
Szymon Jancc35938b2011-03-22 13:12:21 +01003658 if (err < 0)
3659 mgmt_pending_remove(cmd);
3660
3661unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003662 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003663 return err;
3664}
3665
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003666static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003667 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003668{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003669 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003670 int err;
3671
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003672 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003673
Johan Hedberg5d57e792015-01-23 10:10:38 +02003674 if (!bdaddr_type_is_valid(addr->type))
3675 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3676 MGMT_STATUS_INVALID_PARAMS, addr,
3677 sizeof(*addr));
3678
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003679 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003680
Marcel Holtmannec109112014-01-10 02:07:30 -08003681 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3682 struct mgmt_cp_add_remote_oob_data *cp = data;
3683 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003684
Johan Hedbergc19a4952014-11-17 20:52:19 +02003685 if (cp->addr.type != BDADDR_BREDR) {
3686 err = cmd_complete(sk, hdev->id,
3687 MGMT_OP_ADD_REMOTE_OOB_DATA,
3688 MGMT_STATUS_INVALID_PARAMS,
3689 &cp->addr, sizeof(cp->addr));
3690 goto unlock;
3691 }
3692
Marcel Holtmannec109112014-01-10 02:07:30 -08003693 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003694 cp->addr.type, cp->hash,
3695 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003696 if (err < 0)
3697 status = MGMT_STATUS_FAILED;
3698 else
3699 status = MGMT_STATUS_SUCCESS;
3700
3701 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3702 status, &cp->addr, sizeof(cp->addr));
3703 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3704 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003705 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003706 u8 status;
3707
Johan Hedberg86df9202014-10-26 20:52:27 +01003708 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003709 /* Enforce zero-valued 192-bit parameters as
3710 * long as legacy SMP OOB isn't implemented.
3711 */
3712 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3713 memcmp(cp->hash192, ZERO_KEY, 16)) {
3714 err = cmd_complete(sk, hdev->id,
3715 MGMT_OP_ADD_REMOTE_OOB_DATA,
3716 MGMT_STATUS_INVALID_PARAMS,
3717 addr, sizeof(*addr));
3718 goto unlock;
3719 }
3720
Johan Hedberg86df9202014-10-26 20:52:27 +01003721 rand192 = NULL;
3722 hash192 = NULL;
3723 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003724 /* In case one of the P-192 values is set to zero,
3725 * then just disable OOB data for P-192.
3726 */
3727 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3728 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3729 rand192 = NULL;
3730 hash192 = NULL;
3731 } else {
3732 rand192 = cp->rand192;
3733 hash192 = cp->hash192;
3734 }
3735 }
3736
3737 /* In case one of the P-256 values is set to zero, then just
3738 * disable OOB data for P-256.
3739 */
3740 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3741 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3742 rand256 = NULL;
3743 hash256 = NULL;
3744 } else {
3745 rand256 = cp->rand256;
3746 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003747 }
3748
Johan Hedberg81328d52014-10-26 20:33:47 +01003749 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003750 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003751 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003752 if (err < 0)
3753 status = MGMT_STATUS_FAILED;
3754 else
3755 status = MGMT_STATUS_SUCCESS;
3756
3757 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3758 status, &cp->addr, sizeof(cp->addr));
3759 } else {
3760 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3761 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3762 MGMT_STATUS_INVALID_PARAMS);
3763 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003764
Johan Hedbergc19a4952014-11-17 20:52:19 +02003765unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003766 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003767 return err;
3768}
3769
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003770static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003771 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003772{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003773 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003774 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003775 int err;
3776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003777 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003778
Johan Hedbergc19a4952014-11-17 20:52:19 +02003779 if (cp->addr.type != BDADDR_BREDR)
3780 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3781 MGMT_STATUS_INVALID_PARAMS,
3782 &cp->addr, sizeof(cp->addr));
3783
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003784 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003785
Johan Hedbergeedbd582014-11-15 09:34:23 +02003786 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3787 hci_remote_oob_data_clear(hdev);
3788 status = MGMT_STATUS_SUCCESS;
3789 goto done;
3790 }
3791
Johan Hedberg6928a922014-10-26 20:46:09 +01003792 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003793 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003794 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003795 else
Szymon Janca6785be2012-12-13 15:11:21 +01003796 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003797
Johan Hedbergeedbd582014-11-15 09:34:23 +02003798done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003799 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003800 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003801
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003802 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003803 return err;
3804}
3805
Marcel Holtmann80190442014-12-04 11:36:36 +01003806static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003807{
Marcel Holtmann80190442014-12-04 11:36:36 +01003808 struct hci_dev *hdev = req->hdev;
3809 struct hci_cp_le_set_scan_param param_cp;
3810 struct hci_cp_le_set_scan_enable enable_cp;
3811 struct hci_cp_inquiry inq_cp;
3812 /* General inquiry access code (GIAC) */
3813 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3814 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003815 int err;
3816
Marcel Holtmann80190442014-12-04 11:36:36 +01003817 switch (hdev->discovery.type) {
3818 case DISCOV_TYPE_BREDR:
3819 *status = mgmt_bredr_support(hdev);
3820 if (*status)
3821 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003822
Marcel Holtmann80190442014-12-04 11:36:36 +01003823 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3824 *status = MGMT_STATUS_BUSY;
3825 return false;
3826 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003827
Marcel Holtmann80190442014-12-04 11:36:36 +01003828 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003829
Marcel Holtmann80190442014-12-04 11:36:36 +01003830 memset(&inq_cp, 0, sizeof(inq_cp));
3831 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3832 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3833 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3834 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003835
Marcel Holtmann80190442014-12-04 11:36:36 +01003836 case DISCOV_TYPE_LE:
3837 case DISCOV_TYPE_INTERLEAVED:
3838 *status = mgmt_le_support(hdev);
3839 if (*status)
3840 return false;
3841
3842 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3843 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3844 *status = MGMT_STATUS_NOT_SUPPORTED;
3845 return false;
3846 }
3847
3848 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3849 /* Don't let discovery abort an outgoing
3850 * connection attempt that's using directed
3851 * advertising.
3852 */
3853 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3854 BT_CONNECT)) {
3855 *status = MGMT_STATUS_REJECTED;
3856 return false;
3857 }
3858
3859 disable_advertising(req);
3860 }
3861
3862 /* If controller is scanning, it means the background scanning
3863 * is running. Thus, we should temporarily stop it in order to
3864 * set the discovery scanning parameters.
3865 */
3866 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3867 hci_req_add_le_scan_disable(req);
3868
3869 memset(&param_cp, 0, sizeof(param_cp));
3870
3871 /* All active scans will be done with either a resolvable
3872 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003873 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003874 */
3875 err = hci_update_random_address(req, true, &own_addr_type);
3876 if (err < 0) {
3877 *status = MGMT_STATUS_FAILED;
3878 return false;
3879 }
3880
3881 param_cp.type = LE_SCAN_ACTIVE;
3882 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3883 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3884 param_cp.own_address_type = own_addr_type;
3885 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3886 &param_cp);
3887
3888 memset(&enable_cp, 0, sizeof(enable_cp));
3889 enable_cp.enable = LE_SCAN_ENABLE;
3890 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3891 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3892 &enable_cp);
3893 break;
3894
3895 default:
3896 *status = MGMT_STATUS_INVALID_PARAMS;
3897 return false;
3898 }
3899
3900 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003901}
3902
Marcel Holtmann1904a852015-01-11 13:50:44 -08003903static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3904 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003905{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003906 struct pending_cmd *cmd;
3907 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003908
Andre Guedes7c307722013-04-30 15:29:28 -03003909 BT_DBG("status %d", status);
3910
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003911 hci_dev_lock(hdev);
3912
3913 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003914 if (!cmd)
3915 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3916
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003917 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003918 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003919 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003920 }
3921
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003922 if (status) {
3923 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3924 goto unlock;
3925 }
3926
Andre Guedes7c307722013-04-30 15:29:28 -03003927 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003928
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003929 /* If the scan involves LE scan, pick proper timeout to schedule
3930 * hdev->le_scan_disable that will stop it.
3931 */
Andre Guedes7c307722013-04-30 15:29:28 -03003932 switch (hdev->discovery.type) {
3933 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003934 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003935 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003936 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003937 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003938 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003939 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003940 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003941 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003942 default:
3943 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003944 timeout = 0;
3945 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003946 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003947
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003948 if (timeout) {
3949 /* When service discovery is used and the controller has
3950 * a strict duplicate filter, it is important to remember
3951 * the start and duration of the scan. This is required
3952 * for restarting scanning during the discovery phase.
3953 */
3954 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3955 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003956 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003957 hdev->discovery.scan_start = jiffies;
3958 hdev->discovery.scan_duration = timeout;
3959 }
3960
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003961 queue_delayed_work(hdev->workqueue,
3962 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003963 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003964
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003965unlock:
3966 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003967}
3968
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003969static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003970 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003971{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003972 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003973 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003974 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003975 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003976 int err;
3977
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003978 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003979
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003980 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003981
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003982 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003983 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3984 MGMT_STATUS_NOT_POWERED,
3985 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003986 goto failed;
3987 }
3988
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003989 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3990 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003991 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3992 MGMT_STATUS_BUSY, &cp->type,
3993 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003994 goto failed;
3995 }
3996
Johan Hedberg2922a942014-12-05 13:36:06 +02003997 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003998 if (!cmd) {
3999 err = -ENOMEM;
4000 goto failed;
4001 }
4002
Johan Hedberg2922a942014-12-05 13:36:06 +02004003 cmd->cmd_complete = generic_cmd_complete;
4004
Marcel Holtmann22078802014-12-05 11:45:22 +01004005 /* Clear the discovery filter first to free any previously
4006 * allocated memory for the UUID list.
4007 */
4008 hci_discovery_filter_clear(hdev);
4009
Andre Guedes4aab14e2012-02-17 20:39:36 -03004010 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004011 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004012
Andre Guedes7c307722013-04-30 15:29:28 -03004013 hci_req_init(&req, hdev);
4014
Marcel Holtmann80190442014-12-04 11:36:36 +01004015 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01004016 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01004017 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004018 mgmt_pending_remove(cmd);
4019 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004020 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004021
Andre Guedes7c307722013-04-30 15:29:28 -03004022 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004023 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004024 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004025 goto failed;
4026 }
4027
4028 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004029
4030failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004031 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004032 return err;
4033}
4034
Johan Hedberg9df74652014-12-19 22:26:03 +02004035static int service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004036{
Johan Hedberg9df74652014-12-19 22:26:03 +02004037 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4038 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004039}
4040
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004041static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4042 void *data, u16 len)
4043{
4044 struct mgmt_cp_start_service_discovery *cp = data;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004045 struct pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004046 struct hci_request req;
4047 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4048 u16 uuid_count, expected_len;
4049 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004050 int err;
4051
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004052 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004053
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004054 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004055
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004056 if (!hdev_is_powered(hdev)) {
4057 err = cmd_complete(sk, hdev->id,
4058 MGMT_OP_START_SERVICE_DISCOVERY,
4059 MGMT_STATUS_NOT_POWERED,
4060 &cp->type, sizeof(cp->type));
4061 goto failed;
4062 }
4063
4064 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4065 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
4066 err = cmd_complete(sk, hdev->id,
4067 MGMT_OP_START_SERVICE_DISCOVERY,
4068 MGMT_STATUS_BUSY, &cp->type,
4069 sizeof(cp->type));
4070 goto failed;
4071 }
4072
4073 uuid_count = __le16_to_cpu(cp->uuid_count);
4074 if (uuid_count > max_uuid_count) {
4075 BT_ERR("service_discovery: too big uuid_count value %u",
4076 uuid_count);
4077 err = cmd_complete(sk, hdev->id,
4078 MGMT_OP_START_SERVICE_DISCOVERY,
4079 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4080 sizeof(cp->type));
4081 goto failed;
4082 }
4083
4084 expected_len = sizeof(*cp) + uuid_count * 16;
4085 if (expected_len != len) {
4086 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4087 expected_len, len);
4088 err = cmd_complete(sk, hdev->id,
4089 MGMT_OP_START_SERVICE_DISCOVERY,
4090 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4091 sizeof(cp->type));
4092 goto failed;
4093 }
4094
4095 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004096 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004097 if (!cmd) {
4098 err = -ENOMEM;
4099 goto failed;
4100 }
4101
Johan Hedberg2922a942014-12-05 13:36:06 +02004102 cmd->cmd_complete = service_discovery_cmd_complete;
4103
Marcel Holtmann22078802014-12-05 11:45:22 +01004104 /* Clear the discovery filter first to free any previously
4105 * allocated memory for the UUID list.
4106 */
4107 hci_discovery_filter_clear(hdev);
4108
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004109 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004110 hdev->discovery.type = cp->type;
4111 hdev->discovery.rssi = cp->rssi;
4112 hdev->discovery.uuid_count = uuid_count;
4113
4114 if (uuid_count > 0) {
4115 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4116 GFP_KERNEL);
4117 if (!hdev->discovery.uuids) {
4118 err = cmd_complete(sk, hdev->id,
4119 MGMT_OP_START_SERVICE_DISCOVERY,
4120 MGMT_STATUS_FAILED,
4121 &cp->type, sizeof(cp->type));
4122 mgmt_pending_remove(cmd);
4123 goto failed;
4124 }
4125 }
4126
4127 hci_req_init(&req, hdev);
4128
4129 if (!trigger_discovery(&req, &status)) {
4130 err = cmd_complete(sk, hdev->id,
4131 MGMT_OP_START_SERVICE_DISCOVERY,
4132 status, &cp->type, sizeof(cp->type));
4133 mgmt_pending_remove(cmd);
4134 goto failed;
4135 }
4136
4137 err = hci_req_run(&req, start_discovery_complete);
4138 if (err < 0) {
4139 mgmt_pending_remove(cmd);
4140 goto failed;
4141 }
4142
4143 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4144
4145failed:
4146 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004147 return err;
4148}
4149
Marcel Holtmann1904a852015-01-11 13:50:44 -08004150static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004151{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004152 struct pending_cmd *cmd;
4153
Andre Guedes0e05bba2013-04-30 15:29:33 -03004154 BT_DBG("status %d", status);
4155
4156 hci_dev_lock(hdev);
4157
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004158 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4159 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004160 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004161 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004162 }
4163
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004164 if (!status)
4165 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004166
Andre Guedes0e05bba2013-04-30 15:29:33 -03004167 hci_dev_unlock(hdev);
4168}
4169
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004170static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004171 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004172{
Johan Hedbergd9306502012-02-20 23:25:18 +02004173 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004174 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004175 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004176 int err;
4177
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004178 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004179
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004180 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004181
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004182 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004183 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004184 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4185 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004186 goto unlock;
4187 }
4188
4189 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004190 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004191 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4192 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004193 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004194 }
4195
Johan Hedberg2922a942014-12-05 13:36:06 +02004196 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004197 if (!cmd) {
4198 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004199 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004200 }
4201
Johan Hedberg2922a942014-12-05 13:36:06 +02004202 cmd->cmd_complete = generic_cmd_complete;
4203
Andre Guedes0e05bba2013-04-30 15:29:33 -03004204 hci_req_init(&req, hdev);
4205
Johan Hedberg21a60d32014-06-10 14:05:58 +03004206 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004207
Johan Hedberg21a60d32014-06-10 14:05:58 +03004208 err = hci_req_run(&req, stop_discovery_complete);
4209 if (!err) {
4210 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004211 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004212 }
4213
Johan Hedberg21a60d32014-06-10 14:05:58 +03004214 mgmt_pending_remove(cmd);
4215
4216 /* If no HCI commands were sent we're done */
4217 if (err == -ENODATA) {
4218 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4219 &mgmt_cp->type, sizeof(mgmt_cp->type));
4220 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4221 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004222
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004223unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004224 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004225 return err;
4226}
4227
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004228static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004229 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004230{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004231 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004232 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004233 int err;
4234
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004235 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004236
Johan Hedberg561aafb2012-01-04 13:31:59 +02004237 hci_dev_lock(hdev);
4238
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004239 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004240 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4241 MGMT_STATUS_FAILED, &cp->addr,
4242 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004243 goto failed;
4244 }
4245
Johan Hedberga198e7b2012-02-17 14:27:06 +02004246 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004247 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004248 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4249 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4250 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004251 goto failed;
4252 }
4253
4254 if (cp->name_known) {
4255 e->name_state = NAME_KNOWN;
4256 list_del(&e->list);
4257 } else {
4258 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004259 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004260 }
4261
Johan Hedberge3846622013-01-09 15:29:33 +02004262 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4263 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004264
4265failed:
4266 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004267 return err;
4268}
4269
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004270static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004271 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004272{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004273 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004274 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004275 int err;
4276
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004277 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004278
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004279 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004280 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4281 MGMT_STATUS_INVALID_PARAMS,
4282 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004283
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004284 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004285
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004286 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4287 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004288 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004289 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004290 goto done;
4291 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004292
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004293 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4294 sk);
4295 status = MGMT_STATUS_SUCCESS;
4296
4297done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004298 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004299 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004300
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004301 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004302
4303 return err;
4304}
4305
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004306static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004307 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004308{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004309 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004310 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004311 int err;
4312
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004313 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004314
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004315 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004316 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4317 MGMT_STATUS_INVALID_PARAMS,
4318 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004319
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004320 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004321
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004322 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4323 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004324 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004325 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004326 goto done;
4327 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004328
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004329 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4330 sk);
4331 status = MGMT_STATUS_SUCCESS;
4332
4333done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004334 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004335 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004336
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004337 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004338
4339 return err;
4340}
4341
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004342static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4343 u16 len)
4344{
4345 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004346 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004347 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004348 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004349
4350 BT_DBG("%s", hdev->name);
4351
Szymon Jancc72d4b82012-03-16 16:02:57 +01004352 source = __le16_to_cpu(cp->source);
4353
4354 if (source > 0x0002)
4355 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4356 MGMT_STATUS_INVALID_PARAMS);
4357
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004358 hci_dev_lock(hdev);
4359
Szymon Jancc72d4b82012-03-16 16:02:57 +01004360 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004361 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4362 hdev->devid_product = __le16_to_cpu(cp->product);
4363 hdev->devid_version = __le16_to_cpu(cp->version);
4364
4365 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4366
Johan Hedberg890ea892013-03-15 17:06:52 -05004367 hci_req_init(&req, hdev);
4368 update_eir(&req);
4369 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004370
4371 hci_dev_unlock(hdev);
4372
4373 return err;
4374}
4375
Marcel Holtmann1904a852015-01-11 13:50:44 -08004376static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4377 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004378{
4379 struct cmd_lookup match = { NULL, hdev };
4380
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304381 hci_dev_lock(hdev);
4382
Johan Hedberg4375f102013-09-25 13:26:10 +03004383 if (status) {
4384 u8 mgmt_err = mgmt_status(status);
4385
4386 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4387 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304388 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004389 }
4390
Johan Hedbergc93bd152014-07-08 15:07:48 +03004391 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4392 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4393 else
4394 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4395
Johan Hedberg4375f102013-09-25 13:26:10 +03004396 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4397 &match);
4398
4399 new_settings(hdev, match.sk);
4400
4401 if (match.sk)
4402 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304403
4404unlock:
4405 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004406}
4407
Marcel Holtmann21b51872013-10-10 09:47:53 -07004408static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4409 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004410{
4411 struct mgmt_mode *cp = data;
4412 struct pending_cmd *cmd;
4413 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004414 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004415 int err;
4416
4417 BT_DBG("request for %s", hdev->name);
4418
Johan Hedberge6fe7982013-10-02 15:45:22 +03004419 status = mgmt_le_support(hdev);
4420 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004421 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004422 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004423
4424 if (cp->val != 0x00 && cp->val != 0x01)
4425 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4426 MGMT_STATUS_INVALID_PARAMS);
4427
4428 hci_dev_lock(hdev);
4429
4430 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004431 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004432
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004433 /* The following conditions are ones which mean that we should
4434 * not do any HCI communication but directly send a mgmt
4435 * response to user space (after toggling the flag if
4436 * necessary).
4437 */
4438 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004439 hci_conn_num(hdev, LE_LINK) > 0 ||
4440 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4441 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004442 bool changed = false;
4443
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004444 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4445 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004446 changed = true;
4447 }
4448
4449 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4450 if (err < 0)
4451 goto unlock;
4452
4453 if (changed)
4454 err = new_settings(hdev, sk);
4455
4456 goto unlock;
4457 }
4458
4459 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4460 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4461 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4462 MGMT_STATUS_BUSY);
4463 goto unlock;
4464 }
4465
4466 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4467 if (!cmd) {
4468 err = -ENOMEM;
4469 goto unlock;
4470 }
4471
4472 hci_req_init(&req, hdev);
4473
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004474 if (val)
4475 enable_advertising(&req);
4476 else
4477 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004478
4479 err = hci_req_run(&req, set_advertising_complete);
4480 if (err < 0)
4481 mgmt_pending_remove(cmd);
4482
4483unlock:
4484 hci_dev_unlock(hdev);
4485 return err;
4486}
4487
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004488static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4489 void *data, u16 len)
4490{
4491 struct mgmt_cp_set_static_address *cp = data;
4492 int err;
4493
4494 BT_DBG("%s", hdev->name);
4495
Marcel Holtmann62af4442013-10-02 22:10:32 -07004496 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004497 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004498 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004499
4500 if (hdev_is_powered(hdev))
4501 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4502 MGMT_STATUS_REJECTED);
4503
4504 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4505 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4506 return cmd_status(sk, hdev->id,
4507 MGMT_OP_SET_STATIC_ADDRESS,
4508 MGMT_STATUS_INVALID_PARAMS);
4509
4510 /* Two most significant bits shall be set */
4511 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4512 return cmd_status(sk, hdev->id,
4513 MGMT_OP_SET_STATIC_ADDRESS,
4514 MGMT_STATUS_INVALID_PARAMS);
4515 }
4516
4517 hci_dev_lock(hdev);
4518
4519 bacpy(&hdev->static_addr, &cp->bdaddr);
4520
Marcel Holtmann93690c22015-03-06 10:11:21 -08004521 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4522 if (err < 0)
4523 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004524
Marcel Holtmann93690c22015-03-06 10:11:21 -08004525 err = new_settings(hdev, sk);
4526
4527unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004528 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004529 return err;
4530}
4531
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004532static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4533 void *data, u16 len)
4534{
4535 struct mgmt_cp_set_scan_params *cp = data;
4536 __u16 interval, window;
4537 int err;
4538
4539 BT_DBG("%s", hdev->name);
4540
4541 if (!lmp_le_capable(hdev))
4542 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4543 MGMT_STATUS_NOT_SUPPORTED);
4544
4545 interval = __le16_to_cpu(cp->interval);
4546
4547 if (interval < 0x0004 || interval > 0x4000)
4548 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4549 MGMT_STATUS_INVALID_PARAMS);
4550
4551 window = __le16_to_cpu(cp->window);
4552
4553 if (window < 0x0004 || window > 0x4000)
4554 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4555 MGMT_STATUS_INVALID_PARAMS);
4556
Marcel Holtmann899e1072013-10-14 09:55:32 -07004557 if (window > interval)
4558 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4559 MGMT_STATUS_INVALID_PARAMS);
4560
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004561 hci_dev_lock(hdev);
4562
4563 hdev->le_scan_interval = interval;
4564 hdev->le_scan_window = window;
4565
4566 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4567
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004568 /* If background scan is running, restart it so new parameters are
4569 * loaded.
4570 */
4571 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4572 hdev->discovery.state == DISCOVERY_STOPPED) {
4573 struct hci_request req;
4574
4575 hci_req_init(&req, hdev);
4576
4577 hci_req_add_le_scan_disable(&req);
4578 hci_req_add_le_passive_scan(&req);
4579
4580 hci_req_run(&req, NULL);
4581 }
4582
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004583 hci_dev_unlock(hdev);
4584
4585 return err;
4586}
4587
Marcel Holtmann1904a852015-01-11 13:50:44 -08004588static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4589 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004590{
4591 struct pending_cmd *cmd;
4592
4593 BT_DBG("status 0x%02x", status);
4594
4595 hci_dev_lock(hdev);
4596
4597 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4598 if (!cmd)
4599 goto unlock;
4600
4601 if (status) {
4602 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4603 mgmt_status(status));
4604 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004605 struct mgmt_mode *cp = cmd->param;
4606
4607 if (cp->val)
4608 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4609 else
4610 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4611
Johan Hedberg33e38b32013-03-15 17:07:05 -05004612 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4613 new_settings(hdev, cmd->sk);
4614 }
4615
4616 mgmt_pending_remove(cmd);
4617
4618unlock:
4619 hci_dev_unlock(hdev);
4620}
4621
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004622static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004623 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004624{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004625 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004626 struct pending_cmd *cmd;
4627 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004628 int err;
4629
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004630 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004631
Johan Hedberg56f87902013-10-02 13:43:13 +03004632 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4633 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004634 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4635 MGMT_STATUS_NOT_SUPPORTED);
4636
Johan Hedberga7e80f22013-01-09 16:05:19 +02004637 if (cp->val != 0x00 && cp->val != 0x01)
4638 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4639 MGMT_STATUS_INVALID_PARAMS);
4640
Johan Hedberg5400c042012-02-21 16:40:33 +02004641 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004642 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004643 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004644
4645 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004646 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004647 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004648
4649 hci_dev_lock(hdev);
4650
Johan Hedberg05cbf292013-03-15 17:07:07 -05004651 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4652 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4653 MGMT_STATUS_BUSY);
4654 goto unlock;
4655 }
4656
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004657 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4658 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4659 hdev);
4660 goto unlock;
4661 }
4662
Johan Hedberg33e38b32013-03-15 17:07:05 -05004663 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4664 data, len);
4665 if (!cmd) {
4666 err = -ENOMEM;
4667 goto unlock;
4668 }
4669
4670 hci_req_init(&req, hdev);
4671
Johan Hedberg406d7802013-03-15 17:07:09 -05004672 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004673
4674 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004675 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004676 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004677 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004678 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004679 }
4680
Johan Hedberg33e38b32013-03-15 17:07:05 -05004681unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004682 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004683
Antti Julkuf6422ec2011-06-22 13:11:56 +03004684 return err;
4685}
4686
Marcel Holtmann1904a852015-01-11 13:50:44 -08004687static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004688{
4689 struct pending_cmd *cmd;
4690
4691 BT_DBG("status 0x%02x", status);
4692
4693 hci_dev_lock(hdev);
4694
4695 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4696 if (!cmd)
4697 goto unlock;
4698
4699 if (status) {
4700 u8 mgmt_err = mgmt_status(status);
4701
4702 /* We need to restore the flag if related HCI commands
4703 * failed.
4704 */
4705 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4706
4707 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4708 } else {
4709 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4710 new_settings(hdev, cmd->sk);
4711 }
4712
4713 mgmt_pending_remove(cmd);
4714
4715unlock:
4716 hci_dev_unlock(hdev);
4717}
4718
4719static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4720{
4721 struct mgmt_mode *cp = data;
4722 struct pending_cmd *cmd;
4723 struct hci_request req;
4724 int err;
4725
4726 BT_DBG("request for %s", hdev->name);
4727
4728 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4729 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4730 MGMT_STATUS_NOT_SUPPORTED);
4731
4732 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4733 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4734 MGMT_STATUS_REJECTED);
4735
4736 if (cp->val != 0x00 && cp->val != 0x01)
4737 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4738 MGMT_STATUS_INVALID_PARAMS);
4739
4740 hci_dev_lock(hdev);
4741
4742 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4743 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4744 goto unlock;
4745 }
4746
4747 if (!hdev_is_powered(hdev)) {
4748 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004749 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4750 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4751 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4752 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4753 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4754 }
4755
4756 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4757
4758 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4759 if (err < 0)
4760 goto unlock;
4761
4762 err = new_settings(hdev, sk);
4763 goto unlock;
4764 }
4765
4766 /* Reject disabling when powered on */
4767 if (!cp->val) {
4768 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4769 MGMT_STATUS_REJECTED);
4770 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004771 } else {
4772 /* When configuring a dual-mode controller to operate
4773 * with LE only and using a static address, then switching
4774 * BR/EDR back on is not allowed.
4775 *
4776 * Dual-mode controllers shall operate with the public
4777 * address as its identity address for BR/EDR and LE. So
4778 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004779 *
4780 * The same restrictions applies when secure connections
4781 * has been enabled. For BR/EDR this is a controller feature
4782 * while for LE it is a host stack feature. This means that
4783 * switching BR/EDR back on when secure connections has been
4784 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004785 */
4786 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004787 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4788 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004789 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4790 MGMT_STATUS_REJECTED);
4791 goto unlock;
4792 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004793 }
4794
4795 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4796 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4797 MGMT_STATUS_BUSY);
4798 goto unlock;
4799 }
4800
4801 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4802 if (!cmd) {
4803 err = -ENOMEM;
4804 goto unlock;
4805 }
4806
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004807 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004808 * generates the correct flags.
4809 */
4810 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4811
4812 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004813
Johan Hedberg432df052014-08-01 11:13:31 +03004814 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004815 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004816
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004817 /* Since only the advertising data flags will change, there
4818 * is no need to update the scan response data.
4819 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004820 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004821
Johan Hedberg0663ca22013-10-02 13:43:14 +03004822 err = hci_req_run(&req, set_bredr_complete);
4823 if (err < 0)
4824 mgmt_pending_remove(cmd);
4825
4826unlock:
4827 hci_dev_unlock(hdev);
4828 return err;
4829}
4830
Johan Hedberga1443f52015-01-23 15:42:46 +02004831static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4832{
4833 struct pending_cmd *cmd;
4834 struct mgmt_mode *cp;
4835
4836 BT_DBG("%s status %u", hdev->name, status);
4837
4838 hci_dev_lock(hdev);
4839
4840 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4841 if (!cmd)
4842 goto unlock;
4843
4844 if (status) {
4845 cmd_status(cmd->sk, cmd->index, cmd->opcode,
4846 mgmt_status(status));
4847 goto remove;
4848 }
4849
4850 cp = cmd->param;
4851
4852 switch (cp->val) {
4853 case 0x00:
4854 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4855 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4856 break;
4857 case 0x01:
4858 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4859 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4860 break;
4861 case 0x02:
4862 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4863 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4864 break;
4865 }
4866
4867 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4868 new_settings(hdev, cmd->sk);
4869
4870remove:
4871 mgmt_pending_remove(cmd);
4872unlock:
4873 hci_dev_unlock(hdev);
4874}
4875
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004876static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4877 void *data, u16 len)
4878{
4879 struct mgmt_mode *cp = data;
4880 struct pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004881 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004882 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004883 int err;
4884
4885 BT_DBG("request for %s", hdev->name);
4886
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004887 if (!lmp_sc_capable(hdev) &&
4888 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004889 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4890 MGMT_STATUS_NOT_SUPPORTED);
4891
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004892 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004893 lmp_sc_capable(hdev) &&
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004894 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
4895 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4896 MGMT_STATUS_REJECTED);
4897
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004898 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004899 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4900 MGMT_STATUS_INVALID_PARAMS);
4901
4902 hci_dev_lock(hdev);
4903
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004904 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004905 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004906 bool changed;
4907
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004908 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004909 changed = !test_and_set_bit(HCI_SC_ENABLED,
4910 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004911 if (cp->val == 0x02)
4912 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4913 else
4914 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4915 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004916 changed = test_and_clear_bit(HCI_SC_ENABLED,
4917 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004918 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4919 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004920
4921 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4922 if (err < 0)
4923 goto failed;
4924
4925 if (changed)
4926 err = new_settings(hdev, sk);
4927
4928 goto failed;
4929 }
4930
4931 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4932 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4933 MGMT_STATUS_BUSY);
4934 goto failed;
4935 }
4936
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004937 val = !!cp->val;
4938
4939 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4940 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004941 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4942 goto failed;
4943 }
4944
4945 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4946 if (!cmd) {
4947 err = -ENOMEM;
4948 goto failed;
4949 }
4950
Johan Hedberga1443f52015-01-23 15:42:46 +02004951 hci_req_init(&req, hdev);
4952 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4953 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004954 if (err < 0) {
4955 mgmt_pending_remove(cmd);
4956 goto failed;
4957 }
4958
4959failed:
4960 hci_dev_unlock(hdev);
4961 return err;
4962}
4963
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004964static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4965 void *data, u16 len)
4966{
4967 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004968 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004969 int err;
4970
4971 BT_DBG("request for %s", hdev->name);
4972
Johan Hedbergb97109792014-06-24 14:00:28 +03004973 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004974 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4975 MGMT_STATUS_INVALID_PARAMS);
4976
4977 hci_dev_lock(hdev);
4978
4979 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004980 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4981 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004982 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004983 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4984 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004985
Johan Hedbergb97109792014-06-24 14:00:28 +03004986 if (cp->val == 0x02)
4987 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4988 &hdev->dev_flags);
4989 else
4990 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4991 &hdev->dev_flags);
4992
4993 if (hdev_is_powered(hdev) && use_changed &&
4994 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4995 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4996 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4997 sizeof(mode), &mode);
4998 }
4999
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005000 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5001 if (err < 0)
5002 goto unlock;
5003
5004 if (changed)
5005 err = new_settings(hdev, sk);
5006
5007unlock:
5008 hci_dev_unlock(hdev);
5009 return err;
5010}
5011
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005012static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5013 u16 len)
5014{
5015 struct mgmt_cp_set_privacy *cp = cp_data;
5016 bool changed;
5017 int err;
5018
5019 BT_DBG("request for %s", hdev->name);
5020
5021 if (!lmp_le_capable(hdev))
5022 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5023 MGMT_STATUS_NOT_SUPPORTED);
5024
5025 if (cp->privacy != 0x00 && cp->privacy != 0x01)
5026 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5027 MGMT_STATUS_INVALID_PARAMS);
5028
5029 if (hdev_is_powered(hdev))
5030 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5031 MGMT_STATUS_REJECTED);
5032
5033 hci_dev_lock(hdev);
5034
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005035 /* If user space supports this command it is also expected to
5036 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5037 */
5038 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5039
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005040 if (cp->privacy) {
5041 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5042 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5043 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5044 } else {
5045 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5046 memset(hdev->irk, 0, sizeof(hdev->irk));
5047 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5048 }
5049
5050 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5051 if (err < 0)
5052 goto unlock;
5053
5054 if (changed)
5055 err = new_settings(hdev, sk);
5056
5057unlock:
5058 hci_dev_unlock(hdev);
5059 return err;
5060}
5061
Johan Hedberg41edf162014-02-18 10:19:35 +02005062static bool irk_is_valid(struct mgmt_irk_info *irk)
5063{
5064 switch (irk->addr.type) {
5065 case BDADDR_LE_PUBLIC:
5066 return true;
5067
5068 case BDADDR_LE_RANDOM:
5069 /* Two most significant bits shall be set */
5070 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5071 return false;
5072 return true;
5073 }
5074
5075 return false;
5076}
5077
5078static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5079 u16 len)
5080{
5081 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005082 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5083 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005084 u16 irk_count, expected_len;
5085 int i, err;
5086
5087 BT_DBG("request for %s", hdev->name);
5088
5089 if (!lmp_le_capable(hdev))
5090 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5091 MGMT_STATUS_NOT_SUPPORTED);
5092
5093 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005094 if (irk_count > max_irk_count) {
5095 BT_ERR("load_irks: too big irk_count value %u", irk_count);
5096 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5097 MGMT_STATUS_INVALID_PARAMS);
5098 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005099
5100 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5101 if (expected_len != len) {
5102 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005103 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02005104 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5105 MGMT_STATUS_INVALID_PARAMS);
5106 }
5107
5108 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5109
5110 for (i = 0; i < irk_count; i++) {
5111 struct mgmt_irk_info *key = &cp->irks[i];
5112
5113 if (!irk_is_valid(key))
5114 return cmd_status(sk, hdev->id,
5115 MGMT_OP_LOAD_IRKS,
5116 MGMT_STATUS_INVALID_PARAMS);
5117 }
5118
5119 hci_dev_lock(hdev);
5120
5121 hci_smp_irks_clear(hdev);
5122
5123 for (i = 0; i < irk_count; i++) {
5124 struct mgmt_irk_info *irk = &cp->irks[i];
5125 u8 addr_type;
5126
5127 if (irk->addr.type == BDADDR_LE_PUBLIC)
5128 addr_type = ADDR_LE_DEV_PUBLIC;
5129 else
5130 addr_type = ADDR_LE_DEV_RANDOM;
5131
5132 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5133 BDADDR_ANY);
5134 }
5135
5136 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5137
5138 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
5139
5140 hci_dev_unlock(hdev);
5141
5142 return err;
5143}
5144
Johan Hedberg3f706b72013-01-20 14:27:16 +02005145static bool ltk_is_valid(struct mgmt_ltk_info *key)
5146{
5147 if (key->master != 0x00 && key->master != 0x01)
5148 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005149
5150 switch (key->addr.type) {
5151 case BDADDR_LE_PUBLIC:
5152 return true;
5153
5154 case BDADDR_LE_RANDOM:
5155 /* Two most significant bits shall be set */
5156 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5157 return false;
5158 return true;
5159 }
5160
5161 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005162}
5163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005164static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005165 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005166{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005167 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005168 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5169 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005170 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005171 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005172
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005173 BT_DBG("request for %s", hdev->name);
5174
5175 if (!lmp_le_capable(hdev))
5176 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5177 MGMT_STATUS_NOT_SUPPORTED);
5178
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005179 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005180 if (key_count > max_key_count) {
5181 BT_ERR("load_ltks: too big key_count value %u", key_count);
5182 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5183 MGMT_STATUS_INVALID_PARAMS);
5184 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005185
5186 expected_len = sizeof(*cp) + key_count *
5187 sizeof(struct mgmt_ltk_info);
5188 if (expected_len != len) {
5189 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005190 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005191 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005192 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005193 }
5194
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005195 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005196
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005197 for (i = 0; i < key_count; i++) {
5198 struct mgmt_ltk_info *key = &cp->keys[i];
5199
Johan Hedberg3f706b72013-01-20 14:27:16 +02005200 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005201 return cmd_status(sk, hdev->id,
5202 MGMT_OP_LOAD_LONG_TERM_KEYS,
5203 MGMT_STATUS_INVALID_PARAMS);
5204 }
5205
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005206 hci_dev_lock(hdev);
5207
5208 hci_smp_ltks_clear(hdev);
5209
5210 for (i = 0; i < key_count; i++) {
5211 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005212 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005213
5214 if (key->addr.type == BDADDR_LE_PUBLIC)
5215 addr_type = ADDR_LE_DEV_PUBLIC;
5216 else
5217 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005218
Johan Hedberg61b43352014-05-29 19:36:53 +03005219 switch (key->type) {
5220 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005221 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005222 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005223 break;
5224 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005225 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005226 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005227 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005228 case MGMT_LTK_P256_UNAUTH:
5229 authenticated = 0x00;
5230 type = SMP_LTK_P256;
5231 break;
5232 case MGMT_LTK_P256_AUTH:
5233 authenticated = 0x01;
5234 type = SMP_LTK_P256;
5235 break;
5236 case MGMT_LTK_P256_DEBUG:
5237 authenticated = 0x00;
5238 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005239 default:
5240 continue;
5241 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005242
Johan Hedberg35d70272014-02-19 14:57:47 +02005243 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005244 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005245 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005246 }
5247
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005248 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5249 NULL, 0);
5250
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005251 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005252
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005253 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005254}
5255
Johan Hedberg9df74652014-12-19 22:26:03 +02005256static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005257{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005258 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005259 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005260 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005261
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005262 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005263
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005264 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005265 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005266 rp.tx_power = conn->tx_power;
5267 rp.max_tx_power = conn->max_tx_power;
5268 } else {
5269 rp.rssi = HCI_RSSI_INVALID;
5270 rp.tx_power = HCI_TX_POWER_INVALID;
5271 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005272 }
5273
Johan Hedberg9df74652014-12-19 22:26:03 +02005274 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5275 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005276
5277 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005278 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005279
5280 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005281}
5282
Marcel Holtmann1904a852015-01-11 13:50:44 -08005283static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5284 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005285{
5286 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005287 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005288 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005289 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005290 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005291
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005292 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005293
5294 hci_dev_lock(hdev);
5295
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005296 /* Commands sent in request are either Read RSSI or Read Transmit Power
5297 * Level so we check which one was last sent to retrieve connection
5298 * handle. Both commands have handle as first parameter so it's safe to
5299 * cast data on the same command struct.
5300 *
5301 * First command sent is always Read RSSI and we fail only if it fails.
5302 * In other case we simply override error to indicate success as we
5303 * already remembered if TX power value is actually valid.
5304 */
5305 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5306 if (!cp) {
5307 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005308 status = MGMT_STATUS_SUCCESS;
5309 } else {
5310 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005311 }
5312
5313 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005314 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005315 goto unlock;
5316 }
5317
5318 handle = __le16_to_cpu(cp->handle);
5319 conn = hci_conn_hash_lookup_handle(hdev, handle);
5320 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005321 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005322 goto unlock;
5323 }
5324
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005325 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5326 if (!cmd)
5327 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005328
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005329 cmd->cmd_complete(cmd, status);
5330 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005331
5332unlock:
5333 hci_dev_unlock(hdev);
5334}
5335
5336static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5337 u16 len)
5338{
5339 struct mgmt_cp_get_conn_info *cp = data;
5340 struct mgmt_rp_get_conn_info rp;
5341 struct hci_conn *conn;
5342 unsigned long conn_info_age;
5343 int err = 0;
5344
5345 BT_DBG("%s", hdev->name);
5346
5347 memset(&rp, 0, sizeof(rp));
5348 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5349 rp.addr.type = cp->addr.type;
5350
5351 if (!bdaddr_type_is_valid(cp->addr.type))
5352 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5353 MGMT_STATUS_INVALID_PARAMS,
5354 &rp, sizeof(rp));
5355
5356 hci_dev_lock(hdev);
5357
5358 if (!hdev_is_powered(hdev)) {
5359 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5360 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5361 goto unlock;
5362 }
5363
5364 if (cp->addr.type == BDADDR_BREDR)
5365 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5366 &cp->addr.bdaddr);
5367 else
5368 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5369
5370 if (!conn || conn->state != BT_CONNECTED) {
5371 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5372 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5373 goto unlock;
5374 }
5375
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005376 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5377 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5378 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5379 goto unlock;
5380 }
5381
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005382 /* To avoid client trying to guess when to poll again for information we
5383 * calculate conn info age as random value between min/max set in hdev.
5384 */
5385 conn_info_age = hdev->conn_info_min_age +
5386 prandom_u32_max(hdev->conn_info_max_age -
5387 hdev->conn_info_min_age);
5388
5389 /* Query controller to refresh cached values if they are too old or were
5390 * never read.
5391 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005392 if (time_after(jiffies, conn->conn_info_timestamp +
5393 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005394 !conn->conn_info_timestamp) {
5395 struct hci_request req;
5396 struct hci_cp_read_tx_power req_txp_cp;
5397 struct hci_cp_read_rssi req_rssi_cp;
5398 struct pending_cmd *cmd;
5399
5400 hci_req_init(&req, hdev);
5401 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5402 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5403 &req_rssi_cp);
5404
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005405 /* For LE links TX power does not change thus we don't need to
5406 * query for it once value is known.
5407 */
5408 if (!bdaddr_type_is_le(cp->addr.type) ||
5409 conn->tx_power == HCI_TX_POWER_INVALID) {
5410 req_txp_cp.handle = cpu_to_le16(conn->handle);
5411 req_txp_cp.type = 0x00;
5412 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5413 sizeof(req_txp_cp), &req_txp_cp);
5414 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005415
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005416 /* Max TX power needs to be read only once per connection */
5417 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5418 req_txp_cp.handle = cpu_to_le16(conn->handle);
5419 req_txp_cp.type = 0x01;
5420 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5421 sizeof(req_txp_cp), &req_txp_cp);
5422 }
5423
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005424 err = hci_req_run(&req, conn_info_refresh_complete);
5425 if (err < 0)
5426 goto unlock;
5427
5428 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5429 data, len);
5430 if (!cmd) {
5431 err = -ENOMEM;
5432 goto unlock;
5433 }
5434
5435 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005436 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005437 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005438
5439 conn->conn_info_timestamp = jiffies;
5440 } else {
5441 /* Cache is valid, just reply with values cached in hci_conn */
5442 rp.rssi = conn->rssi;
5443 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005444 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005445
5446 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5447 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5448 }
5449
5450unlock:
5451 hci_dev_unlock(hdev);
5452 return err;
5453}
5454
Johan Hedberg9df74652014-12-19 22:26:03 +02005455static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005456{
5457 struct hci_conn *conn = cmd->user_data;
5458 struct mgmt_rp_get_clock_info rp;
5459 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005460 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005461
5462 memset(&rp, 0, sizeof(rp));
5463 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5464
5465 if (status)
5466 goto complete;
5467
5468 hdev = hci_dev_get(cmd->index);
5469 if (hdev) {
5470 rp.local_clock = cpu_to_le32(hdev->clock);
5471 hci_dev_put(hdev);
5472 }
5473
5474 if (conn) {
5475 rp.piconet_clock = cpu_to_le32(conn->clock);
5476 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5477 }
5478
5479complete:
Johan Hedberg9df74652014-12-19 22:26:03 +02005480 err = cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5481 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005482
5483 if (conn) {
5484 hci_conn_drop(conn);
5485 hci_conn_put(conn);
5486 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005487
5488 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005489}
5490
Marcel Holtmann1904a852015-01-11 13:50:44 -08005491static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005492{
Johan Hedberg95868422014-06-28 17:54:07 +03005493 struct hci_cp_read_clock *hci_cp;
5494 struct pending_cmd *cmd;
5495 struct hci_conn *conn;
5496
5497 BT_DBG("%s status %u", hdev->name, status);
5498
5499 hci_dev_lock(hdev);
5500
5501 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5502 if (!hci_cp)
5503 goto unlock;
5504
5505 if (hci_cp->which) {
5506 u16 handle = __le16_to_cpu(hci_cp->handle);
5507 conn = hci_conn_hash_lookup_handle(hdev, handle);
5508 } else {
5509 conn = NULL;
5510 }
5511
5512 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5513 if (!cmd)
5514 goto unlock;
5515
Johan Hedberg69487372014-12-05 13:36:07 +02005516 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005517 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005518
5519unlock:
5520 hci_dev_unlock(hdev);
5521}
5522
5523static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5524 u16 len)
5525{
5526 struct mgmt_cp_get_clock_info *cp = data;
5527 struct mgmt_rp_get_clock_info rp;
5528 struct hci_cp_read_clock hci_cp;
5529 struct pending_cmd *cmd;
5530 struct hci_request req;
5531 struct hci_conn *conn;
5532 int err;
5533
5534 BT_DBG("%s", hdev->name);
5535
5536 memset(&rp, 0, sizeof(rp));
5537 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5538 rp.addr.type = cp->addr.type;
5539
5540 if (cp->addr.type != BDADDR_BREDR)
5541 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5542 MGMT_STATUS_INVALID_PARAMS,
5543 &rp, sizeof(rp));
5544
5545 hci_dev_lock(hdev);
5546
5547 if (!hdev_is_powered(hdev)) {
5548 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5549 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5550 goto unlock;
5551 }
5552
5553 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5554 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5555 &cp->addr.bdaddr);
5556 if (!conn || conn->state != BT_CONNECTED) {
5557 err = cmd_complete(sk, hdev->id,
5558 MGMT_OP_GET_CLOCK_INFO,
5559 MGMT_STATUS_NOT_CONNECTED,
5560 &rp, sizeof(rp));
5561 goto unlock;
5562 }
5563 } else {
5564 conn = NULL;
5565 }
5566
5567 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5568 if (!cmd) {
5569 err = -ENOMEM;
5570 goto unlock;
5571 }
5572
Johan Hedberg69487372014-12-05 13:36:07 +02005573 cmd->cmd_complete = clock_info_cmd_complete;
5574
Johan Hedberg95868422014-06-28 17:54:07 +03005575 hci_req_init(&req, hdev);
5576
5577 memset(&hci_cp, 0, sizeof(hci_cp));
5578 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5579
5580 if (conn) {
5581 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005582 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005583
5584 hci_cp.handle = cpu_to_le16(conn->handle);
5585 hci_cp.which = 0x01; /* Piconet clock */
5586 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5587 }
5588
5589 err = hci_req_run(&req, get_clock_info_complete);
5590 if (err < 0)
5591 mgmt_pending_remove(cmd);
5592
5593unlock:
5594 hci_dev_unlock(hdev);
5595 return err;
5596}
5597
Johan Hedberg5a154e62014-12-19 22:26:02 +02005598static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5599{
5600 struct hci_conn *conn;
5601
5602 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5603 if (!conn)
5604 return false;
5605
5606 if (conn->dst_type != type)
5607 return false;
5608
5609 if (conn->state != BT_CONNECTED)
5610 return false;
5611
5612 return true;
5613}
5614
5615/* This function requires the caller holds hdev->lock */
5616static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5617 u8 addr_type, u8 auto_connect)
5618{
5619 struct hci_dev *hdev = req->hdev;
5620 struct hci_conn_params *params;
5621
5622 params = hci_conn_params_add(hdev, addr, addr_type);
5623 if (!params)
5624 return -EIO;
5625
5626 if (params->auto_connect == auto_connect)
5627 return 0;
5628
5629 list_del_init(&params->action);
5630
5631 switch (auto_connect) {
5632 case HCI_AUTO_CONN_DISABLED:
5633 case HCI_AUTO_CONN_LINK_LOSS:
5634 __hci_update_background_scan(req);
5635 break;
5636 case HCI_AUTO_CONN_REPORT:
5637 list_add(&params->action, &hdev->pend_le_reports);
5638 __hci_update_background_scan(req);
5639 break;
5640 case HCI_AUTO_CONN_DIRECT:
5641 case HCI_AUTO_CONN_ALWAYS:
5642 if (!is_connected(hdev, addr, addr_type)) {
5643 list_add(&params->action, &hdev->pend_le_conns);
5644 __hci_update_background_scan(req);
5645 }
5646 break;
5647 }
5648
5649 params->auto_connect = auto_connect;
5650
5651 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5652 auto_connect);
5653
5654 return 0;
5655}
5656
Marcel Holtmann8afef092014-06-29 22:28:34 +02005657static void device_added(struct sock *sk, struct hci_dev *hdev,
5658 bdaddr_t *bdaddr, u8 type, u8 action)
5659{
5660 struct mgmt_ev_device_added ev;
5661
5662 bacpy(&ev.addr.bdaddr, bdaddr);
5663 ev.addr.type = type;
5664 ev.action = action;
5665
5666 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5667}
5668
Marcel Holtmann1904a852015-01-11 13:50:44 -08005669static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005670{
5671 struct pending_cmd *cmd;
5672
5673 BT_DBG("status 0x%02x", status);
5674
5675 hci_dev_lock(hdev);
5676
5677 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5678 if (!cmd)
5679 goto unlock;
5680
5681 cmd->cmd_complete(cmd, mgmt_status(status));
5682 mgmt_pending_remove(cmd);
5683
5684unlock:
5685 hci_dev_unlock(hdev);
5686}
5687
Marcel Holtmann2faade52014-06-29 19:44:03 +02005688static int add_device(struct sock *sk, struct hci_dev *hdev,
5689 void *data, u16 len)
5690{
5691 struct mgmt_cp_add_device *cp = data;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005692 struct pending_cmd *cmd;
5693 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005694 u8 auto_conn, addr_type;
5695 int err;
5696
5697 BT_DBG("%s", hdev->name);
5698
Johan Hedberg66593582014-07-09 12:59:14 +03005699 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005700 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5701 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5702 MGMT_STATUS_INVALID_PARAMS,
5703 &cp->addr, sizeof(cp->addr));
5704
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005705 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005706 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5707 MGMT_STATUS_INVALID_PARAMS,
5708 &cp->addr, sizeof(cp->addr));
5709
Johan Hedberg5a154e62014-12-19 22:26:02 +02005710 hci_req_init(&req, hdev);
5711
Marcel Holtmann2faade52014-06-29 19:44:03 +02005712 hci_dev_lock(hdev);
5713
Johan Hedberg5a154e62014-12-19 22:26:02 +02005714 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5715 if (!cmd) {
5716 err = -ENOMEM;
5717 goto unlock;
5718 }
5719
5720 cmd->cmd_complete = addr_cmd_complete;
5721
Johan Hedberg66593582014-07-09 12:59:14 +03005722 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005723 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005724 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005725 err = cmd->cmd_complete(cmd,
5726 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005727 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005728 goto unlock;
5729 }
5730
5731 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5732 cp->addr.type);
5733 if (err)
5734 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005735
Johan Hedberg5a154e62014-12-19 22:26:02 +02005736 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005737
Johan Hedberg66593582014-07-09 12:59:14 +03005738 goto added;
5739 }
5740
Marcel Holtmann2faade52014-06-29 19:44:03 +02005741 if (cp->addr.type == BDADDR_LE_PUBLIC)
5742 addr_type = ADDR_LE_DEV_PUBLIC;
5743 else
5744 addr_type = ADDR_LE_DEV_RANDOM;
5745
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005746 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005747 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005748 else if (cp->action == 0x01)
5749 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005750 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005751 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005752
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005753 /* If the connection parameters don't exist for this device,
5754 * they will be created and configured with defaults.
5755 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005756 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005757 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005758 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005759 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005760 goto unlock;
5761 }
5762
Johan Hedberg66593582014-07-09 12:59:14 +03005763added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005764 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5765
Johan Hedberg5a154e62014-12-19 22:26:02 +02005766 err = hci_req_run(&req, add_device_complete);
5767 if (err < 0) {
5768 /* ENODATA means no HCI commands were needed (e.g. if
5769 * the adapter is powered off).
5770 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005771 if (err == -ENODATA)
5772 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005773 mgmt_pending_remove(cmd);
5774 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005775
5776unlock:
5777 hci_dev_unlock(hdev);
5778 return err;
5779}
5780
Marcel Holtmann8afef092014-06-29 22:28:34 +02005781static void device_removed(struct sock *sk, struct hci_dev *hdev,
5782 bdaddr_t *bdaddr, u8 type)
5783{
5784 struct mgmt_ev_device_removed ev;
5785
5786 bacpy(&ev.addr.bdaddr, bdaddr);
5787 ev.addr.type = type;
5788
5789 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5790}
5791
Marcel Holtmann1904a852015-01-11 13:50:44 -08005792static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005793{
5794 struct pending_cmd *cmd;
5795
5796 BT_DBG("status 0x%02x", status);
5797
5798 hci_dev_lock(hdev);
5799
5800 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5801 if (!cmd)
5802 goto unlock;
5803
5804 cmd->cmd_complete(cmd, mgmt_status(status));
5805 mgmt_pending_remove(cmd);
5806
5807unlock:
5808 hci_dev_unlock(hdev);
5809}
5810
Marcel Holtmann2faade52014-06-29 19:44:03 +02005811static int remove_device(struct sock *sk, struct hci_dev *hdev,
5812 void *data, u16 len)
5813{
5814 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005815 struct pending_cmd *cmd;
5816 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005817 int err;
5818
5819 BT_DBG("%s", hdev->name);
5820
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005821 hci_req_init(&req, hdev);
5822
Marcel Holtmann2faade52014-06-29 19:44:03 +02005823 hci_dev_lock(hdev);
5824
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005825 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5826 if (!cmd) {
5827 err = -ENOMEM;
5828 goto unlock;
5829 }
5830
5831 cmd->cmd_complete = addr_cmd_complete;
5832
Marcel Holtmann2faade52014-06-29 19:44:03 +02005833 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005834 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005835 u8 addr_type;
5836
Johan Hedberg66593582014-07-09 12:59:14 +03005837 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005838 err = cmd->cmd_complete(cmd,
5839 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005840 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005841 goto unlock;
5842 }
5843
Johan Hedberg66593582014-07-09 12:59:14 +03005844 if (cp->addr.type == BDADDR_BREDR) {
5845 err = hci_bdaddr_list_del(&hdev->whitelist,
5846 &cp->addr.bdaddr,
5847 cp->addr.type);
5848 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005849 err = cmd->cmd_complete(cmd,
5850 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005851 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005852 goto unlock;
5853 }
5854
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005855 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005856
Johan Hedberg66593582014-07-09 12:59:14 +03005857 device_removed(sk, hdev, &cp->addr.bdaddr,
5858 cp->addr.type);
5859 goto complete;
5860 }
5861
Marcel Holtmann2faade52014-06-29 19:44:03 +02005862 if (cp->addr.type == BDADDR_LE_PUBLIC)
5863 addr_type = ADDR_LE_DEV_PUBLIC;
5864 else
5865 addr_type = ADDR_LE_DEV_RANDOM;
5866
Johan Hedbergc71593d2014-07-02 17:37:28 +03005867 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5868 addr_type);
5869 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005870 err = cmd->cmd_complete(cmd,
5871 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005872 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005873 goto unlock;
5874 }
5875
5876 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005877 err = cmd->cmd_complete(cmd,
5878 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005879 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005880 goto unlock;
5881 }
5882
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005883 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005884 list_del(&params->list);
5885 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005886 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005887
5888 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005889 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005890 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005891 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005892
Marcel Holtmann2faade52014-06-29 19:44:03 +02005893 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005894 err = cmd->cmd_complete(cmd,
5895 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005896 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005897 goto unlock;
5898 }
5899
Johan Hedberg66593582014-07-09 12:59:14 +03005900 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5901 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5902 list_del(&b->list);
5903 kfree(b);
5904 }
5905
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005906 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005907
Johan Hedberg19de0822014-07-06 13:06:51 +03005908 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5909 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5910 continue;
5911 device_removed(sk, hdev, &p->addr, p->addr_type);
5912 list_del(&p->action);
5913 list_del(&p->list);
5914 kfree(p);
5915 }
5916
5917 BT_DBG("All LE connection parameters were removed");
5918
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005919 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005920 }
5921
Johan Hedberg66593582014-07-09 12:59:14 +03005922complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005923 err = hci_req_run(&req, remove_device_complete);
5924 if (err < 0) {
5925 /* ENODATA means no HCI commands were needed (e.g. if
5926 * the adapter is powered off).
5927 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005928 if (err == -ENODATA)
5929 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005930 mgmt_pending_remove(cmd);
5931 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005932
5933unlock:
5934 hci_dev_unlock(hdev);
5935 return err;
5936}
5937
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005938static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5939 u16 len)
5940{
5941 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005942 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5943 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005944 u16 param_count, expected_len;
5945 int i;
5946
5947 if (!lmp_le_capable(hdev))
5948 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5949 MGMT_STATUS_NOT_SUPPORTED);
5950
5951 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005952 if (param_count > max_param_count) {
5953 BT_ERR("load_conn_param: too big param_count value %u",
5954 param_count);
5955 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5956 MGMT_STATUS_INVALID_PARAMS);
5957 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005958
5959 expected_len = sizeof(*cp) + param_count *
5960 sizeof(struct mgmt_conn_param);
5961 if (expected_len != len) {
5962 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5963 expected_len, len);
5964 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5965 MGMT_STATUS_INVALID_PARAMS);
5966 }
5967
5968 BT_DBG("%s param_count %u", hdev->name, param_count);
5969
5970 hci_dev_lock(hdev);
5971
5972 hci_conn_params_clear_disabled(hdev);
5973
5974 for (i = 0; i < param_count; i++) {
5975 struct mgmt_conn_param *param = &cp->params[i];
5976 struct hci_conn_params *hci_param;
5977 u16 min, max, latency, timeout;
5978 u8 addr_type;
5979
5980 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5981 param->addr.type);
5982
5983 if (param->addr.type == BDADDR_LE_PUBLIC) {
5984 addr_type = ADDR_LE_DEV_PUBLIC;
5985 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5986 addr_type = ADDR_LE_DEV_RANDOM;
5987 } else {
5988 BT_ERR("Ignoring invalid connection parameters");
5989 continue;
5990 }
5991
5992 min = le16_to_cpu(param->min_interval);
5993 max = le16_to_cpu(param->max_interval);
5994 latency = le16_to_cpu(param->latency);
5995 timeout = le16_to_cpu(param->timeout);
5996
5997 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5998 min, max, latency, timeout);
5999
6000 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6001 BT_ERR("Ignoring invalid connection parameters");
6002 continue;
6003 }
6004
6005 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6006 addr_type);
6007 if (!hci_param) {
6008 BT_ERR("Failed to add connection parameters");
6009 continue;
6010 }
6011
6012 hci_param->conn_min_interval = min;
6013 hci_param->conn_max_interval = max;
6014 hci_param->conn_latency = latency;
6015 hci_param->supervision_timeout = timeout;
6016 }
6017
6018 hci_dev_unlock(hdev);
6019
6020 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
6021}
6022
Marcel Holtmanndbece372014-07-04 18:11:55 +02006023static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6024 void *data, u16 len)
6025{
6026 struct mgmt_cp_set_external_config *cp = data;
6027 bool changed;
6028 int err;
6029
6030 BT_DBG("%s", hdev->name);
6031
6032 if (hdev_is_powered(hdev))
6033 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6034 MGMT_STATUS_REJECTED);
6035
6036 if (cp->config != 0x00 && cp->config != 0x01)
6037 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6038 MGMT_STATUS_INVALID_PARAMS);
6039
6040 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
6041 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6042 MGMT_STATUS_NOT_SUPPORTED);
6043
6044 hci_dev_lock(hdev);
6045
6046 if (cp->config)
6047 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6048 &hdev->dev_flags);
6049 else
6050 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6051 &hdev->dev_flags);
6052
6053 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6054 if (err < 0)
6055 goto unlock;
6056
6057 if (!changed)
6058 goto unlock;
6059
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006060 err = new_options(hdev, sk);
6061
Marcel Holtmanndbece372014-07-04 18:11:55 +02006062 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
6063 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006064
6065 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6066 set_bit(HCI_CONFIG, &hdev->dev_flags);
6067 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6068
6069 queue_work(hdev->req_workqueue, &hdev->power_on);
6070 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006071 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006072 mgmt_index_added(hdev);
6073 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006074 }
6075
6076unlock:
6077 hci_dev_unlock(hdev);
6078 return err;
6079}
6080
Marcel Holtmann9713c172014-07-06 12:11:15 +02006081static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6082 void *data, u16 len)
6083{
6084 struct mgmt_cp_set_public_address *cp = data;
6085 bool changed;
6086 int err;
6087
6088 BT_DBG("%s", hdev->name);
6089
6090 if (hdev_is_powered(hdev))
6091 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6092 MGMT_STATUS_REJECTED);
6093
6094 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
6095 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6096 MGMT_STATUS_INVALID_PARAMS);
6097
6098 if (!hdev->set_bdaddr)
6099 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6100 MGMT_STATUS_NOT_SUPPORTED);
6101
6102 hci_dev_lock(hdev);
6103
6104 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6105 bacpy(&hdev->public_addr, &cp->bdaddr);
6106
6107 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6108 if (err < 0)
6109 goto unlock;
6110
6111 if (!changed)
6112 goto unlock;
6113
6114 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6115 err = new_options(hdev, sk);
6116
6117 if (is_configured(hdev)) {
6118 mgmt_index_removed(hdev);
6119
6120 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6121
6122 set_bit(HCI_CONFIG, &hdev->dev_flags);
6123 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6124
6125 queue_work(hdev->req_workqueue, &hdev->power_on);
6126 }
6127
6128unlock:
6129 hci_dev_unlock(hdev);
6130 return err;
6131}
6132
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006133static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006134 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
6135 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006136 bool var_len;
6137 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006138} mgmt_handlers[] = {
6139 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02006140 { read_version, false, MGMT_READ_VERSION_SIZE },
6141 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
6142 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
6143 { read_controller_info, false, MGMT_READ_INFO_SIZE },
6144 { set_powered, false, MGMT_SETTING_SIZE },
6145 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
6146 { set_connectable, false, MGMT_SETTING_SIZE },
6147 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03006148 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006149 { set_link_security, false, MGMT_SETTING_SIZE },
6150 { set_ssp, false, MGMT_SETTING_SIZE },
6151 { set_hs, false, MGMT_SETTING_SIZE },
6152 { set_le, false, MGMT_SETTING_SIZE },
6153 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
6154 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
6155 { add_uuid, false, MGMT_ADD_UUID_SIZE },
6156 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
6157 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
6158 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
6159 { disconnect, false, MGMT_DISCONNECT_SIZE },
6160 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
6161 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
6162 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6163 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
6164 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
6165 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6166 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
6167 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
6168 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6169 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
6170 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
6171 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08006172 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006173 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6174 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
6175 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
6176 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
6177 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
6178 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07006179 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03006180 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03006181 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006182 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07006183 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006184 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08006185 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02006186 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02006187 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02006188 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03006189 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02006190 { add_device, false, MGMT_ADD_DEVICE_SIZE },
6191 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006192 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
6193 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02006194 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02006195 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02006196 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01006197 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006198};
6199
Johan Hedberg03811012010-12-08 00:21:06 +02006200int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
6201{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006202 void *buf;
6203 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006204 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006205 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006206 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006207 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02006208 int err;
6209
6210 BT_DBG("got %zu bytes", msglen);
6211
6212 if (msglen < sizeof(*hdr))
6213 return -EINVAL;
6214
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006215 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006216 if (!buf)
6217 return -ENOMEM;
6218
Al Viro6ce8e9c2014-04-06 21:25:44 -04006219 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006220 err = -EFAULT;
6221 goto done;
6222 }
6223
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006224 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006225 opcode = __le16_to_cpu(hdr->opcode);
6226 index = __le16_to_cpu(hdr->index);
6227 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006228
6229 if (len != msglen - sizeof(*hdr)) {
6230 err = -EINVAL;
6231 goto done;
6232 }
6233
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006234 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006235 hdev = hci_dev_get(index);
6236 if (!hdev) {
6237 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006238 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006239 goto done;
6240 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006241
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006242 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02006243 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006244 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006245 err = cmd_status(sk, index, opcode,
6246 MGMT_STATUS_INVALID_INDEX);
6247 goto done;
6248 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006249
6250 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02006251 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02006252 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
6253 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006254 err = cmd_status(sk, index, opcode,
6255 MGMT_STATUS_INVALID_INDEX);
6256 goto done;
6257 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006258 }
6259
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006260 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006261 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02006262 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02006263 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006264 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006265 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02006266 }
6267
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006268 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
6269 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
6270 err = cmd_status(sk, index, opcode,
6271 MGMT_STATUS_INVALID_INDEX);
6272 goto done;
6273 }
6274
6275 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
6276 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006277 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006278 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006279 goto done;
6280 }
6281
Johan Hedbergbe22b542012-03-01 22:24:41 +02006282 handler = &mgmt_handlers[opcode];
6283
6284 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006285 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02006286 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006287 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006288 goto done;
6289 }
6290
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006291 if (hdev)
6292 mgmt_init_hdev(sk, hdev);
6293
6294 cp = buf + sizeof(*hdr);
6295
Johan Hedbergbe22b542012-03-01 22:24:41 +02006296 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006297 if (err < 0)
6298 goto done;
6299
Johan Hedberg03811012010-12-08 00:21:06 +02006300 err = msglen;
6301
6302done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006303 if (hdev)
6304 hci_dev_put(hdev);
6305
Johan Hedberg03811012010-12-08 00:21:06 +02006306 kfree(buf);
6307 return err;
6308}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006309
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006310void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006311{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006312 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006313 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006314
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006315 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6316 return;
6317
6318 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6319 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6320 else
6321 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006322}
6323
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006324void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006325{
Johan Hedberg5f159032012-03-02 03:13:19 +02006326 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006327
Marcel Holtmann1514b892013-10-06 08:25:01 -07006328 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006329 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006330
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006331 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6332 return;
6333
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006334 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006335
Marcel Holtmannedd38962014-07-02 21:30:55 +02006336 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6337 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6338 else
6339 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006340}
6341
Andre Guedes6046dc32014-02-26 20:21:51 -03006342/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006343static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006344{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006345 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006346 struct hci_conn_params *p;
6347
6348 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006349 /* Needed for AUTO_OFF case where might not "really"
6350 * have been powered off.
6351 */
6352 list_del_init(&p->action);
6353
6354 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006355 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006356 case HCI_AUTO_CONN_ALWAYS:
6357 list_add(&p->action, &hdev->pend_le_conns);
6358 break;
6359 case HCI_AUTO_CONN_REPORT:
6360 list_add(&p->action, &hdev->pend_le_reports);
6361 break;
6362 default:
6363 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006364 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006365 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006366
Johan Hedberg2cf22212014-12-19 22:26:00 +02006367 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006368}
6369
Marcel Holtmann1904a852015-01-11 13:50:44 -08006370static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006371{
6372 struct cmd_lookup match = { NULL, hdev };
6373
6374 BT_DBG("status 0x%02x", status);
6375
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006376 if (!status) {
6377 /* Register the available SMP channels (BR/EDR and LE) only
6378 * when successfully powering on the controller. This late
6379 * registration is required so that LE SMP can clearly
6380 * decide if the public address or static address is used.
6381 */
6382 smp_register(hdev);
6383 }
6384
Johan Hedberg229ab392013-03-15 17:06:53 -05006385 hci_dev_lock(hdev);
6386
6387 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6388
6389 new_settings(hdev, match.sk);
6390
6391 hci_dev_unlock(hdev);
6392
6393 if (match.sk)
6394 sock_put(match.sk);
6395}
6396
Johan Hedberg70da6242013-03-15 17:06:51 -05006397static int powered_update_hci(struct hci_dev *hdev)
6398{
Johan Hedberg890ea892013-03-15 17:06:52 -05006399 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006400 u8 link_sec;
6401
Johan Hedberg890ea892013-03-15 17:06:52 -05006402 hci_req_init(&req, hdev);
6403
Johan Hedberg70da6242013-03-15 17:06:51 -05006404 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6405 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006406 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006407
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006408 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006409
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006410 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6411 u8 support = 0x01;
6412
6413 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6414 sizeof(support), &support);
6415 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006416 }
6417
Johan Hedbergc73eee92013-04-19 18:35:21 +03006418 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6419 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006420 struct hci_cp_write_le_host_supported cp;
6421
Marcel Holtmann32226e42014-07-24 20:04:16 +02006422 cp.le = 0x01;
6423 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006424
6425 /* Check first if we already have the right
6426 * host state (host features set)
6427 */
6428 if (cp.le != lmp_host_le_capable(hdev) ||
6429 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006430 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6431 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006432 }
6433
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006434 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006435 /* Make sure the controller has a good default for
6436 * advertising data. This also applies to the case
6437 * where BR/EDR was toggled during the AUTO_OFF phase.
6438 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006439 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006440 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006441 update_scan_rsp_data(&req);
6442 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006443
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006444 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6445 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006446
6447 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006448 }
6449
Johan Hedberg70da6242013-03-15 17:06:51 -05006450 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6451 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006452 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6453 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006454
6455 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006456 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006457 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006458 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006459 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006460 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006461 }
6462
Johan Hedberg229ab392013-03-15 17:06:53 -05006463 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006464}
6465
Johan Hedberg744cf192011-11-08 20:40:14 +02006466int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006467{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006468 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006469 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006470 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006471
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006472 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6473 return 0;
6474
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006475 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006476 if (powered_update_hci(hdev) == 0)
6477 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006478
Johan Hedberg229ab392013-03-15 17:06:53 -05006479 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6480 &match);
6481 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006482 }
6483
Johan Hedberg229ab392013-03-15 17:06:53 -05006484 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006485
6486 /* If the power off is because of hdev unregistration let
6487 * use the appropriate INVALID_INDEX status. Otherwise use
6488 * NOT_POWERED. We cover both scenarios here since later in
6489 * mgmt_index_removed() any hci_conn callbacks will have already
6490 * been triggered, potentially causing misleading DISCONNECTED
6491 * status responses.
6492 */
6493 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6494 status = MGMT_STATUS_INVALID_INDEX;
6495 else
6496 status = MGMT_STATUS_NOT_POWERED;
6497
6498 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006499
6500 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6501 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6502 zero_cod, sizeof(zero_cod), NULL);
6503
6504new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006505 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006506
6507 if (match.sk)
6508 sock_put(match.sk);
6509
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006510 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006511}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006512
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006513void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006514{
6515 struct pending_cmd *cmd;
6516 u8 status;
6517
6518 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6519 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006520 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006521
6522 if (err == -ERFKILL)
6523 status = MGMT_STATUS_RFKILLED;
6524 else
6525 status = MGMT_STATUS_FAILED;
6526
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006527 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006528
6529 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006530}
6531
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006532void mgmt_discoverable_timeout(struct hci_dev *hdev)
6533{
6534 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006535
6536 hci_dev_lock(hdev);
6537
6538 /* When discoverable timeout triggers, then just make sure
6539 * the limited discoverable flag is cleared. Even in the case
6540 * of a timeout triggered from general discoverable, it is
6541 * safe to unconditionally clear the flag.
6542 */
6543 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006544 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006545
6546 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006547 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6548 u8 scan = SCAN_PAGE;
6549 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6550 sizeof(scan), &scan);
6551 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006552 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006553 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006554 hci_req_run(&req, NULL);
6555
6556 hdev->discov_timeout = 0;
6557
Johan Hedberg9a43e252013-10-20 19:00:07 +03006558 new_settings(hdev, NULL);
6559
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006560 hci_dev_unlock(hdev);
6561}
6562
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006563void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6564 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006565{
Johan Hedberg86742e12011-11-07 23:13:38 +02006566 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006567
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006568 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006569
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006570 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006571 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006572 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006573 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006574 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006575 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006576
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006577 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006578}
Johan Hedbergf7520542011-01-20 12:34:39 +02006579
Johan Hedbergd7b25452014-05-23 13:19:53 +03006580static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6581{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006582 switch (ltk->type) {
6583 case SMP_LTK:
6584 case SMP_LTK_SLAVE:
6585 if (ltk->authenticated)
6586 return MGMT_LTK_AUTHENTICATED;
6587 return MGMT_LTK_UNAUTHENTICATED;
6588 case SMP_LTK_P256:
6589 if (ltk->authenticated)
6590 return MGMT_LTK_P256_AUTH;
6591 return MGMT_LTK_P256_UNAUTH;
6592 case SMP_LTK_P256_DEBUG:
6593 return MGMT_LTK_P256_DEBUG;
6594 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006595
6596 return MGMT_LTK_UNAUTHENTICATED;
6597}
6598
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006599void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006600{
6601 struct mgmt_ev_new_long_term_key ev;
6602
6603 memset(&ev, 0, sizeof(ev));
6604
Marcel Holtmann5192d302014-02-19 17:11:58 -08006605 /* Devices using resolvable or non-resolvable random addresses
6606 * without providing an indentity resolving key don't require
6607 * to store long term keys. Their addresses will change the
6608 * next time around.
6609 *
6610 * Only when a remote device provides an identity address
6611 * make sure the long term key is stored. If the remote
6612 * identity is known, the long term keys are internally
6613 * mapped to the identity address. So allow static random
6614 * and public addresses here.
6615 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006616 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6617 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6618 ev.store_hint = 0x00;
6619 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006620 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006621
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006622 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006623 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006624 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006625 ev.key.enc_size = key->enc_size;
6626 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006627 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006628
Johan Hedberg2ceba532014-06-16 19:25:16 +03006629 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006630 ev.key.master = 1;
6631
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006632 memcpy(ev.key.val, key->val, sizeof(key->val));
6633
Marcel Holtmann083368f2013-10-15 14:26:29 -07006634 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006635}
6636
Johan Hedberg95fbac82014-02-19 15:18:31 +02006637void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6638{
6639 struct mgmt_ev_new_irk ev;
6640
6641 memset(&ev, 0, sizeof(ev));
6642
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006643 /* For identity resolving keys from devices that are already
6644 * using a public address or static random address, do not
6645 * ask for storing this key. The identity resolving key really
6646 * is only mandatory for devices using resovlable random
6647 * addresses.
6648 *
6649 * Storing all identity resolving keys has the downside that
6650 * they will be also loaded on next boot of they system. More
6651 * identity resolving keys, means more time during scanning is
6652 * needed to actually resolve these addresses.
6653 */
6654 if (bacmp(&irk->rpa, BDADDR_ANY))
6655 ev.store_hint = 0x01;
6656 else
6657 ev.store_hint = 0x00;
6658
Johan Hedberg95fbac82014-02-19 15:18:31 +02006659 bacpy(&ev.rpa, &irk->rpa);
6660 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6661 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6662 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6663
6664 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6665}
6666
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006667void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6668 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006669{
6670 struct mgmt_ev_new_csrk ev;
6671
6672 memset(&ev, 0, sizeof(ev));
6673
6674 /* Devices using resolvable or non-resolvable random addresses
6675 * without providing an indentity resolving key don't require
6676 * to store signature resolving keys. Their addresses will change
6677 * the next time around.
6678 *
6679 * Only when a remote device provides an identity address
6680 * make sure the signature resolving key is stored. So allow
6681 * static random and public addresses here.
6682 */
6683 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6684 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6685 ev.store_hint = 0x00;
6686 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006687 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006688
6689 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6690 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006691 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006692 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6693
6694 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6695}
6696
Andre Guedesffb5a8272014-07-01 18:10:11 -03006697void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006698 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6699 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006700{
6701 struct mgmt_ev_new_conn_param ev;
6702
Johan Hedbergc103aea2014-07-02 17:37:34 +03006703 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6704 return;
6705
Andre Guedesffb5a8272014-07-01 18:10:11 -03006706 memset(&ev, 0, sizeof(ev));
6707 bacpy(&ev.addr.bdaddr, bdaddr);
6708 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006709 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006710 ev.min_interval = cpu_to_le16(min_interval);
6711 ev.max_interval = cpu_to_le16(max_interval);
6712 ev.latency = cpu_to_le16(latency);
6713 ev.timeout = cpu_to_le16(timeout);
6714
6715 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6716}
6717
Marcel Holtmann94933992013-10-15 10:26:39 -07006718static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6719 u8 data_len)
6720{
6721 eir[eir_len++] = sizeof(type) + data_len;
6722 eir[eir_len++] = type;
6723 memcpy(&eir[eir_len], data, data_len);
6724 eir_len += data_len;
6725
6726 return eir_len;
6727}
6728
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006729void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6730 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006731{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006732 char buf[512];
6733 struct mgmt_ev_device_connected *ev = (void *) buf;
6734 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006735
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006736 bacpy(&ev->addr.bdaddr, &conn->dst);
6737 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006738
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006739 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006740
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006741 /* We must ensure that the EIR Data fields are ordered and
6742 * unique. Keep it simple for now and avoid the problem by not
6743 * adding any BR/EDR data to the LE adv.
6744 */
6745 if (conn->le_adv_data_len > 0) {
6746 memcpy(&ev->eir[eir_len],
6747 conn->le_adv_data, conn->le_adv_data_len);
6748 eir_len = conn->le_adv_data_len;
6749 } else {
6750 if (name_len > 0)
6751 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6752 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006753
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006754 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006755 eir_len = eir_append_data(ev->eir, eir_len,
6756 EIR_CLASS_OF_DEV,
6757 conn->dev_class, 3);
6758 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006759
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006760 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006761
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006762 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6763 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006764}
6765
Johan Hedberg8962ee72011-01-20 12:40:27 +02006766static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6767{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006768 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006769
Johan Hedbergf5818c22014-12-05 13:36:02 +02006770 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006771
6772 *sk = cmd->sk;
6773 sock_hold(*sk);
6774
Johan Hedberga664b5b2011-02-19 12:06:02 -03006775 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006776}
6777
Johan Hedberg124f6e32012-02-09 13:50:12 +02006778static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006779{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006780 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006781 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006782
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006783 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6784
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006785 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006786 mgmt_pending_remove(cmd);
6787}
6788
Johan Hedberg84c61d92014-08-01 11:13:30 +03006789bool mgmt_powering_down(struct hci_dev *hdev)
6790{
6791 struct pending_cmd *cmd;
6792 struct mgmt_mode *cp;
6793
6794 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6795 if (!cmd)
6796 return false;
6797
6798 cp = cmd->param;
6799 if (!cp->val)
6800 return true;
6801
6802 return false;
6803}
6804
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006805void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006806 u8 link_type, u8 addr_type, u8 reason,
6807 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006808{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006809 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006810 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006811
Johan Hedberg84c61d92014-08-01 11:13:30 +03006812 /* The connection is still in hci_conn_hash so test for 1
6813 * instead of 0 to know if this is the last one.
6814 */
6815 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6816 cancel_delayed_work(&hdev->power_off);
6817 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006818 }
6819
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006820 if (!mgmt_connected)
6821 return;
6822
Andre Guedes57eb7762013-10-30 19:01:41 -03006823 if (link_type != ACL_LINK && link_type != LE_LINK)
6824 return;
6825
Johan Hedberg744cf192011-11-08 20:40:14 +02006826 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006827
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006828 bacpy(&ev.addr.bdaddr, bdaddr);
6829 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6830 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006831
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006832 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006833
6834 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006835 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006836
Johan Hedberg124f6e32012-02-09 13:50:12 +02006837 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006838 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006839}
6840
Marcel Holtmann78929242013-10-06 23:55:47 -07006841void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6842 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006843{
Andre Guedes3655bba2013-10-30 19:01:40 -03006844 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6845 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006846 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006847
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006848 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6849 hdev);
6850
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006851 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006852 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006853 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006854
Andre Guedes3655bba2013-10-30 19:01:40 -03006855 cp = cmd->param;
6856
6857 if (bacmp(bdaddr, &cp->addr.bdaddr))
6858 return;
6859
6860 if (cp->addr.type != bdaddr_type)
6861 return;
6862
Johan Hedbergf5818c22014-12-05 13:36:02 +02006863 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006864 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006865}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006866
Marcel Holtmann445608d2013-10-06 23:55:48 -07006867void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6868 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006869{
6870 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006871
Johan Hedberg84c61d92014-08-01 11:13:30 +03006872 /* The connection is still in hci_conn_hash so test for 1
6873 * instead of 0 to know if this is the last one.
6874 */
6875 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6876 cancel_delayed_work(&hdev->power_off);
6877 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006878 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006879
Johan Hedberg4c659c32011-11-07 23:13:39 +02006880 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006881 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006882 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006883
Marcel Holtmann445608d2013-10-06 23:55:48 -07006884 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006885}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006886
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006887void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006888{
6889 struct mgmt_ev_pin_code_request ev;
6890
Johan Hedbergd8457692012-02-17 14:24:57 +02006891 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006892 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006893 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006894
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006895 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006896}
6897
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006898void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6899 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006900{
6901 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006902
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006903 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006904 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006905 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006906
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006907 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006908 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006909}
6910
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006911void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6912 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006913{
6914 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006915
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006916 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006917 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006918 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006919
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006920 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006921 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006922}
Johan Hedberga5c29682011-02-19 12:05:57 -03006923
Johan Hedberg744cf192011-11-08 20:40:14 +02006924int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006925 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006926 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006927{
6928 struct mgmt_ev_user_confirm_request ev;
6929
Johan Hedberg744cf192011-11-08 20:40:14 +02006930 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006931
Johan Hedberg272d90d2012-02-09 15:26:12 +02006932 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006933 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006934 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006935 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006936
Johan Hedberg744cf192011-11-08 20:40:14 +02006937 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006938 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006939}
6940
Johan Hedberg272d90d2012-02-09 15:26:12 +02006941int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006942 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006943{
6944 struct mgmt_ev_user_passkey_request ev;
6945
6946 BT_DBG("%s", hdev->name);
6947
Johan Hedberg272d90d2012-02-09 15:26:12 +02006948 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006949 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006950
6951 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006952 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006953}
6954
Brian Gix0df4c182011-11-16 13:53:13 -08006955static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006956 u8 link_type, u8 addr_type, u8 status,
6957 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006958{
6959 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006960
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006961 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006962 if (!cmd)
6963 return -ENOENT;
6964
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006965 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006966 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006967
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006968 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006969}
6970
Johan Hedberg744cf192011-11-08 20:40:14 +02006971int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006972 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006973{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006974 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006975 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006976}
6977
Johan Hedberg272d90d2012-02-09 15:26:12 +02006978int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006979 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006980{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006981 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006982 status,
6983 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006984}
Johan Hedberg2a611692011-02-19 12:06:00 -03006985
Brian Gix604086b2011-11-23 08:28:33 -08006986int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006987 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006988{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006989 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006990 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006991}
6992
Johan Hedberg272d90d2012-02-09 15:26:12 +02006993int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006994 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006995{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006996 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006997 status,
6998 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006999}
7000
Johan Hedberg92a25252012-09-06 18:39:26 +03007001int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7002 u8 link_type, u8 addr_type, u32 passkey,
7003 u8 entered)
7004{
7005 struct mgmt_ev_passkey_notify ev;
7006
7007 BT_DBG("%s", hdev->name);
7008
7009 bacpy(&ev.addr.bdaddr, bdaddr);
7010 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7011 ev.passkey = __cpu_to_le32(passkey);
7012 ev.entered = entered;
7013
7014 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7015}
7016
Johan Hedberge1e930f2014-09-08 17:09:49 -07007017void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007018{
7019 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007020 struct pending_cmd *cmd;
7021 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007022
Johan Hedberge1e930f2014-09-08 17:09:49 -07007023 bacpy(&ev.addr.bdaddr, &conn->dst);
7024 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7025 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007026
Johan Hedberge1e930f2014-09-08 17:09:49 -07007027 cmd = find_pairing(conn);
7028
7029 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7030 cmd ? cmd->sk : NULL);
7031
Johan Hedberga511b352014-12-11 21:45:45 +02007032 if (cmd) {
7033 cmd->cmd_complete(cmd, status);
7034 mgmt_pending_remove(cmd);
7035 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007036}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007037
Marcel Holtmann464996a2013-10-15 14:26:24 -07007038void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007039{
7040 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007041 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007042
7043 if (status) {
7044 u8 mgmt_err = mgmt_status(status);
7045 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007046 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007047 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007048 }
7049
Marcel Holtmann464996a2013-10-15 14:26:24 -07007050 if (test_bit(HCI_AUTH, &hdev->flags))
7051 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7052 &hdev->dev_flags);
7053 else
7054 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7055 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007056
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007057 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007058 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007059
Johan Hedberg47990ea2012-02-22 11:58:37 +02007060 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007061 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007062
7063 if (match.sk)
7064 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007065}
7066
Johan Hedberg890ea892013-03-15 17:06:52 -05007067static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007068{
Johan Hedberg890ea892013-03-15 17:06:52 -05007069 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007070 struct hci_cp_write_eir cp;
7071
Johan Hedberg976eb202012-10-24 21:12:01 +03007072 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007073 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007074
Johan Hedbergc80da272012-02-22 15:38:48 +02007075 memset(hdev->eir, 0, sizeof(hdev->eir));
7076
Johan Hedbergcacaf522012-02-21 00:52:42 +02007077 memset(&cp, 0, sizeof(cp));
7078
Johan Hedberg890ea892013-03-15 17:06:52 -05007079 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007080}
7081
Marcel Holtmann3e248562013-10-15 14:26:25 -07007082void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007083{
7084 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007085 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007086 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007087
7088 if (status) {
7089 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007090
7091 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007092 &hdev->dev_flags)) {
7093 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007094 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007095 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007096
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007097 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7098 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007099 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007100 }
7101
7102 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007103 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007104 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007105 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7106 if (!changed)
7107 changed = test_and_clear_bit(HCI_HS_ENABLED,
7108 &hdev->dev_flags);
7109 else
7110 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007111 }
7112
7113 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7114
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007115 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007116 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007117
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007118 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007119 sock_put(match.sk);
7120
Johan Hedberg890ea892013-03-15 17:06:52 -05007121 hci_req_init(&req, hdev);
7122
Johan Hedberg37699722014-06-24 14:00:27 +03007123 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
7124 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
7125 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7126 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007127 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007128 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007129 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007130 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007131
7132 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007133}
7134
Johan Hedberg92da6092013-03-15 17:06:55 -05007135static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007136{
7137 struct cmd_lookup *match = data;
7138
Johan Hedberg90e70452012-02-23 23:09:40 +02007139 if (match->sk == NULL) {
7140 match->sk = cmd->sk;
7141 sock_hold(match->sk);
7142 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007143}
7144
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007145void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7146 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007147{
Johan Hedberg90e70452012-02-23 23:09:40 +02007148 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007149
Johan Hedberg92da6092013-03-15 17:06:55 -05007150 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7151 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7152 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007153
7154 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007155 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7156 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007157
7158 if (match.sk)
7159 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007160}
7161
Marcel Holtmann7667da32013-10-15 14:26:27 -07007162void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007163{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007164 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05007165 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007166
Johan Hedberg13928972013-03-15 17:07:00 -05007167 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007168 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007169
7170 memset(&ev, 0, sizeof(ev));
7171 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007172 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007173
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007174 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007175 if (!cmd) {
7176 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007177
Johan Hedberg13928972013-03-15 17:07:00 -05007178 /* If this is a HCI command related to powering on the
7179 * HCI dev don't send any mgmt signals.
7180 */
7181 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007182 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007183 }
7184
Marcel Holtmann7667da32013-10-15 14:26:27 -07007185 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7186 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007187}
Szymon Jancc35938b2011-03-22 13:12:21 +01007188
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007189void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007190 u8 *rand192, u8 *hash256, u8 *rand256,
7191 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007192{
7193 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007194
Johan Hedberg744cf192011-11-08 20:40:14 +02007195 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007196
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007197 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007198 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007199 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007200
7201 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007202 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7203 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007204 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007205 struct mgmt_rp_read_local_oob_data rp;
7206 size_t rp_size = sizeof(rp);
7207
7208 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7209 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7210
Johan Hedberg710f11c2014-05-26 11:21:22 +03007211 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007212 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007213 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007214 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007215 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007216 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007217
7218 cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7219 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007220 }
7221
7222 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007223}
Johan Hedberge17acd42011-03-30 23:57:16 +03007224
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007225static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7226{
7227 int i;
7228
7229 for (i = 0; i < uuid_count; i++) {
7230 if (!memcmp(uuid, uuids[i], 16))
7231 return true;
7232 }
7233
7234 return false;
7235}
7236
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007237static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7238{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007239 u16 parsed = 0;
7240
7241 while (parsed < eir_len) {
7242 u8 field_len = eir[0];
7243 u8 uuid[16];
7244 int i;
7245
7246 if (field_len == 0)
7247 break;
7248
7249 if (eir_len - parsed < field_len + 1)
7250 break;
7251
7252 switch (eir[1]) {
7253 case EIR_UUID16_ALL:
7254 case EIR_UUID16_SOME:
7255 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007256 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007257 uuid[13] = eir[i + 3];
7258 uuid[12] = eir[i + 2];
7259 if (has_uuid(uuid, uuid_count, uuids))
7260 return true;
7261 }
7262 break;
7263 case EIR_UUID32_ALL:
7264 case EIR_UUID32_SOME:
7265 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007266 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007267 uuid[15] = eir[i + 5];
7268 uuid[14] = eir[i + 4];
7269 uuid[13] = eir[i + 3];
7270 uuid[12] = eir[i + 2];
7271 if (has_uuid(uuid, uuid_count, uuids))
7272 return true;
7273 }
7274 break;
7275 case EIR_UUID128_ALL:
7276 case EIR_UUID128_SOME:
7277 for (i = 0; i + 17 <= field_len; i += 16) {
7278 memcpy(uuid, eir + i + 2, 16);
7279 if (has_uuid(uuid, uuid_count, uuids))
7280 return true;
7281 }
7282 break;
7283 }
7284
7285 parsed += field_len + 1;
7286 eir += field_len + 1;
7287 }
7288
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007289 return false;
7290}
7291
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007292static void restart_le_scan(struct hci_dev *hdev)
7293{
7294 /* If controller is not scanning we are done. */
7295 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7296 return;
7297
7298 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7299 hdev->discovery.scan_start +
7300 hdev->discovery.scan_duration))
7301 return;
7302
7303 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7304 DISCOV_LE_RESTART_DELAY);
7305}
7306
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007307static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7308 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7309{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007310 /* If a RSSI threshold has been specified, and
7311 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7312 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7313 * is set, let it through for further processing, as we might need to
7314 * restart the scan.
7315 *
7316 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7317 * the results are also dropped.
7318 */
7319 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7320 (rssi == HCI_RSSI_INVALID ||
7321 (rssi < hdev->discovery.rssi &&
7322 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7323 return false;
7324
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007325 if (hdev->discovery.uuid_count != 0) {
7326 /* If a list of UUIDs is provided in filter, results with no
7327 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007328 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007329 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7330 hdev->discovery.uuids) &&
7331 !eir_has_uuids(scan_rsp, scan_rsp_len,
7332 hdev->discovery.uuid_count,
7333 hdev->discovery.uuids))
7334 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007335 }
7336
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007337 /* If duplicate filtering does not report RSSI changes, then restart
7338 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007339 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007340 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7341 restart_le_scan(hdev);
7342
7343 /* Validate RSSI value against the RSSI threshold once more. */
7344 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7345 rssi < hdev->discovery.rssi)
7346 return false;
7347 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007348
7349 return true;
7350}
7351
Marcel Holtmann901801b2013-10-06 23:55:51 -07007352void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007353 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7354 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007355{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007356 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007357 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007358 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007359
Johan Hedberg75ce2082014-07-02 22:42:01 +03007360 /* Don't send events for a non-kernel initiated discovery. With
7361 * LE one exception is if we have pend_le_reports > 0 in which
7362 * case we're doing passive scanning and want these events.
7363 */
7364 if (!hci_discovery_active(hdev)) {
7365 if (link_type == ACL_LINK)
7366 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007367 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007368 return;
7369 }
Andre Guedes12602d02013-04-30 15:29:40 -03007370
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007371 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007372 /* We are using service discovery */
7373 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7374 scan_rsp_len))
7375 return;
7376 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007377
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007378 /* Make sure that the buffer is big enough. The 5 extra bytes
7379 * are for the potential CoD field.
7380 */
7381 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007382 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007383
Johan Hedberg1dc06092012-01-15 21:01:23 +02007384 memset(buf, 0, sizeof(buf));
7385
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007386 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7387 * RSSI value was reported as 0 when not available. This behavior
7388 * is kept when using device discovery. This is required for full
7389 * backwards compatibility with the API.
7390 *
7391 * However when using service discovery, the value 127 will be
7392 * returned when the RSSI is not available.
7393 */
Szymon Janc91200e92015-01-22 16:57:05 +01007394 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7395 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007396 rssi = 0;
7397
Johan Hedberg841c5642014-07-07 12:45:54 +03007398 bacpy(&ev->addr.bdaddr, bdaddr);
7399 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007400 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007401 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007402
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007403 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007404 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007405 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007406
Johan Hedberg1dc06092012-01-15 21:01:23 +02007407 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7408 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007409 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007410
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007411 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007412 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007413 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007414
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007415 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7416 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007417
Marcel Holtmann901801b2013-10-06 23:55:51 -07007418 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007419}
Johan Hedberga88a9652011-03-30 13:18:12 +03007420
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007421void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7422 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007423{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007424 struct mgmt_ev_device_found *ev;
7425 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7426 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007427
Johan Hedbergb644ba32012-01-17 21:48:47 +02007428 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007429
Johan Hedbergb644ba32012-01-17 21:48:47 +02007430 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007431
Johan Hedbergb644ba32012-01-17 21:48:47 +02007432 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007433 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007434 ev->rssi = rssi;
7435
7436 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007437 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007438
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007439 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007440
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007441 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007442}
Johan Hedberg314b2382011-04-27 10:29:57 -04007443
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007444void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007445{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007446 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007447
Andre Guedes343fb142011-11-22 17:14:19 -03007448 BT_DBG("%s discovering %u", hdev->name, discovering);
7449
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007450 memset(&ev, 0, sizeof(ev));
7451 ev.type = hdev->discovery.type;
7452 ev.discovering = discovering;
7453
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007454 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007455}
Antti Julku5e762442011-08-25 16:48:02 +03007456
Marcel Holtmann1904a852015-01-11 13:50:44 -08007457static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007458{
7459 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007460}
7461
7462void mgmt_reenable_advertising(struct hci_dev *hdev)
7463{
7464 struct hci_request req;
7465
Marcel Holtmann5976e602013-10-06 04:08:14 -07007466 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7467 return;
7468
7469 hci_req_init(&req, hdev);
7470 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007471 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007472}