blob: cc67d19a7cb8f910118acce3a06eba11617c201d [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 Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
Johan Hedberg0857dd32014-12-19 13:40:20 +020035#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070036#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020037
Johan Hedberg2da9c552012-02-17 14:39:28 +020038#define MGMT_VERSION 1
Marcel Holtmann854bda12014-12-03 19:52:43 +010039#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020040
Johan Hedberge70bb2e2012-02-13 16:59:33 +020041static const u16 mgmt_commands[] = {
42 MGMT_OP_READ_INDEX_LIST,
43 MGMT_OP_READ_INFO,
44 MGMT_OP_SET_POWERED,
45 MGMT_OP_SET_DISCOVERABLE,
46 MGMT_OP_SET_CONNECTABLE,
47 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030048 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020049 MGMT_OP_SET_LINK_SECURITY,
50 MGMT_OP_SET_SSP,
51 MGMT_OP_SET_HS,
52 MGMT_OP_SET_LE,
53 MGMT_OP_SET_DEV_CLASS,
54 MGMT_OP_SET_LOCAL_NAME,
55 MGMT_OP_ADD_UUID,
56 MGMT_OP_REMOVE_UUID,
57 MGMT_OP_LOAD_LINK_KEYS,
58 MGMT_OP_LOAD_LONG_TERM_KEYS,
59 MGMT_OP_DISCONNECT,
60 MGMT_OP_GET_CONNECTIONS,
61 MGMT_OP_PIN_CODE_REPLY,
62 MGMT_OP_PIN_CODE_NEG_REPLY,
63 MGMT_OP_SET_IO_CAPABILITY,
64 MGMT_OP_PAIR_DEVICE,
65 MGMT_OP_CANCEL_PAIR_DEVICE,
66 MGMT_OP_UNPAIR_DEVICE,
67 MGMT_OP_USER_CONFIRM_REPLY,
68 MGMT_OP_USER_CONFIRM_NEG_REPLY,
69 MGMT_OP_USER_PASSKEY_REPLY,
70 MGMT_OP_USER_PASSKEY_NEG_REPLY,
71 MGMT_OP_READ_LOCAL_OOB_DATA,
72 MGMT_OP_ADD_REMOTE_OOB_DATA,
73 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
74 MGMT_OP_START_DISCOVERY,
75 MGMT_OP_STOP_DISCOVERY,
76 MGMT_OP_CONFIRM_NAME,
77 MGMT_OP_BLOCK_DEVICE,
78 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070079 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030080 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030081 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070082 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070083 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080084 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080085 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020086 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020087 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020088 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030089 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020090 MGMT_OP_ADD_DEVICE,
91 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030092 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020093 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020094 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020095 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020096 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010097 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020098};
99
100static const u16 mgmt_events[] = {
101 MGMT_EV_CONTROLLER_ERROR,
102 MGMT_EV_INDEX_ADDED,
103 MGMT_EV_INDEX_REMOVED,
104 MGMT_EV_NEW_SETTINGS,
105 MGMT_EV_CLASS_OF_DEV_CHANGED,
106 MGMT_EV_LOCAL_NAME_CHANGED,
107 MGMT_EV_NEW_LINK_KEY,
108 MGMT_EV_NEW_LONG_TERM_KEY,
109 MGMT_EV_DEVICE_CONNECTED,
110 MGMT_EV_DEVICE_DISCONNECTED,
111 MGMT_EV_CONNECT_FAILED,
112 MGMT_EV_PIN_CODE_REQUEST,
113 MGMT_EV_USER_CONFIRM_REQUEST,
114 MGMT_EV_USER_PASSKEY_REQUEST,
115 MGMT_EV_AUTH_FAILED,
116 MGMT_EV_DEVICE_FOUND,
117 MGMT_EV_DISCOVERING,
118 MGMT_EV_DEVICE_BLOCKED,
119 MGMT_EV_DEVICE_UNBLOCKED,
120 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300121 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800122 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700123 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200124 MGMT_EV_DEVICE_ADDED,
125 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300126 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200127 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200128 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200129 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200130};
131
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800132#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200133
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200134#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
135 "\x00\x00\x00\x00\x00\x00\x00\x00"
136
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137struct pending_cmd {
138 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200139 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100141 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200142 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200143 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300144 void *user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +0200145 int (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200146};
147
Johan Hedbergca69b792011-11-11 18:10:00 +0200148/* HCI to MGMT error code conversion table */
149static u8 mgmt_status_table[] = {
150 MGMT_STATUS_SUCCESS,
151 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
152 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
153 MGMT_STATUS_FAILED, /* Hardware Failure */
154 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
155 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200156 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200157 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
158 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
159 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
160 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
161 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
162 MGMT_STATUS_BUSY, /* Command Disallowed */
163 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
164 MGMT_STATUS_REJECTED, /* Rejected Security */
165 MGMT_STATUS_REJECTED, /* Rejected Personal */
166 MGMT_STATUS_TIMEOUT, /* Host Timeout */
167 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
168 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
169 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
170 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
171 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
172 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
173 MGMT_STATUS_BUSY, /* Repeated Attempts */
174 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
175 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
176 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
177 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
178 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
179 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
180 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
181 MGMT_STATUS_FAILED, /* Unspecified Error */
182 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
183 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
184 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
185 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
186 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
187 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
188 MGMT_STATUS_FAILED, /* Unit Link Key Used */
189 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
190 MGMT_STATUS_TIMEOUT, /* Instant Passed */
191 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
192 MGMT_STATUS_FAILED, /* Transaction Collision */
193 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
194 MGMT_STATUS_REJECTED, /* QoS Rejected */
195 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
196 MGMT_STATUS_REJECTED, /* Insufficient Security */
197 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
198 MGMT_STATUS_BUSY, /* Role Switch Pending */
199 MGMT_STATUS_FAILED, /* Slot Violation */
200 MGMT_STATUS_FAILED, /* Role Switch Failed */
201 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
202 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
203 MGMT_STATUS_BUSY, /* Host Busy Pairing */
204 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
205 MGMT_STATUS_BUSY, /* Controller Busy */
206 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
207 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
208 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
209 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
210 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
211};
212
213static u8 mgmt_status(u8 hci_status)
214{
215 if (hci_status < ARRAY_SIZE(mgmt_status_table))
216 return mgmt_status_table[hci_status];
217
218 return MGMT_STATUS_FAILED;
219}
220
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200221static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
222 struct sock *skip_sk)
223{
224 struct sk_buff *skb;
225 struct mgmt_hdr *hdr;
226
227 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
228 if (!skb)
229 return -ENOMEM;
230
231 hdr = (void *) skb_put(skb, sizeof(*hdr));
232 hdr->opcode = cpu_to_le16(event);
233 if (hdev)
234 hdr->index = cpu_to_le16(hdev->id);
235 else
236 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
237 hdr->len = cpu_to_le16(data_len);
238
239 if (data)
240 memcpy(skb_put(skb, data_len), data, data_len);
241
242 /* Time stamp */
243 __net_timestamp(skb);
244
245 hci_send_to_control(skb, skip_sk);
246 kfree_skb(skb);
247
248 return 0;
249}
250
Szymon Janc4e51eae2011-02-25 19:05:48 +0100251static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200252{
253 struct sk_buff *skb;
254 struct mgmt_hdr *hdr;
255 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300256 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200257
Szymon Janc34eb5252011-02-28 14:10:08 +0100258 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200259
Andre Guedes790eff42012-06-07 19:05:46 -0300260 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200261 if (!skb)
262 return -ENOMEM;
263
264 hdr = (void *) skb_put(skb, sizeof(*hdr));
265
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700266 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100267 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200268 hdr->len = cpu_to_le16(sizeof(*ev));
269
270 ev = (void *) skb_put(skb, sizeof(*ev));
271 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200272 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 err = sock_queue_rcv_skb(sk, skb);
275 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200276 kfree_skb(skb);
277
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300278 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200279}
280
Johan Hedbergaee9b212012-02-18 15:07:59 +0200281static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300282 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200283{
284 struct sk_buff *skb;
285 struct mgmt_hdr *hdr;
286 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300287 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200288
289 BT_DBG("sock %p", sk);
290
Andre Guedes790eff42012-06-07 19:05:46 -0300291 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200292 if (!skb)
293 return -ENOMEM;
294
295 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200296
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700297 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100298 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200299 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200300
Johan Hedberga38528f2011-01-22 06:46:43 +0200301 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200302 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200303 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100304
305 if (rp)
306 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200307
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300308 err = sock_queue_rcv_skb(sk, skb);
309 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200310 kfree_skb(skb);
311
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100312 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200313}
314
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300315static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
316 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200317{
318 struct mgmt_rp_read_version rp;
319
320 BT_DBG("sock %p", sk);
321
322 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700323 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200324
Johan Hedbergaee9b212012-02-18 15:07:59 +0200325 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300326 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200327}
328
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300329static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
330 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200331{
332 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200333 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
334 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200335 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200336 size_t rp_size;
337 int i, err;
338
339 BT_DBG("sock %p", sk);
340
341 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
342
343 rp = kmalloc(rp_size, GFP_KERNEL);
344 if (!rp)
345 return -ENOMEM;
346
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700347 rp->num_commands = cpu_to_le16(num_commands);
348 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200349
350 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
351 put_unaligned_le16(mgmt_commands[i], opcode);
352
353 for (i = 0; i < num_events; i++, opcode++)
354 put_unaligned_le16(mgmt_events[i], opcode);
355
Johan Hedbergaee9b212012-02-18 15:07:59 +0200356 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300357 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200358 kfree(rp);
359
360 return err;
361}
362
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300363static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
364 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200367 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200368 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200369 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300370 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200371
372 BT_DBG("sock %p", sk);
373
374 read_lock(&hci_dev_list_lock);
375
376 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300377 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200378 if (d->dev_type == HCI_BREDR &&
379 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700380 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200381 }
382
Johan Hedberga38528f2011-01-22 06:46:43 +0200383 rp_len = sizeof(*rp) + (2 * count);
384 rp = kmalloc(rp_len, GFP_ATOMIC);
385 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100386 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200387 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100388 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200389
Johan Hedberg476e44c2012-10-19 20:10:46 +0300390 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200391 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200392 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200393 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200394 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200395 continue;
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397 /* Devices marked as raw-only are neither configured
398 * nor unconfigured controllers.
399 */
400 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700401 continue;
402
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200403 if (d->dev_type == HCI_BREDR &&
404 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700405 rp->index[count++] = cpu_to_le16(d->id);
406 BT_DBG("Added hci%u", d->id);
407 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200408 }
409
Johan Hedberg476e44c2012-10-19 20:10:46 +0300410 rp->num_controllers = cpu_to_le16(count);
411 rp_len = sizeof(*rp) + (2 * count);
412
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413 read_unlock(&hci_dev_list_lock);
414
Johan Hedbergaee9b212012-02-18 15:07:59 +0200415 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300416 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417
Johan Hedberga38528f2011-01-22 06:46:43 +0200418 kfree(rp);
419
420 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200421}
422
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200423static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
424 void *data, u16 data_len)
425{
426 struct mgmt_rp_read_unconf_index_list *rp;
427 struct hci_dev *d;
428 size_t rp_len;
429 u16 count;
430 int err;
431
432 BT_DBG("sock %p", sk);
433
434 read_lock(&hci_dev_list_lock);
435
436 count = 0;
437 list_for_each_entry(d, &hci_dev_list, list) {
438 if (d->dev_type == HCI_BREDR &&
439 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
440 count++;
441 }
442
443 rp_len = sizeof(*rp) + (2 * count);
444 rp = kmalloc(rp_len, GFP_ATOMIC);
445 if (!rp) {
446 read_unlock(&hci_dev_list_lock);
447 return -ENOMEM;
448 }
449
450 count = 0;
451 list_for_each_entry(d, &hci_dev_list, list) {
452 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200453 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200454 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
455 continue;
456
457 /* Devices marked as raw-only are neither configured
458 * nor unconfigured controllers.
459 */
460 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
461 continue;
462
463 if (d->dev_type == HCI_BREDR &&
464 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
465 rp->index[count++] = cpu_to_le16(d->id);
466 BT_DBG("Added hci%u", d->id);
467 }
468 }
469
470 rp->num_controllers = cpu_to_le16(count);
471 rp_len = sizeof(*rp) + (2 * count);
472
473 read_unlock(&hci_dev_list_lock);
474
475 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
476 0, rp, rp_len);
477
478 kfree(rp);
479
480 return err;
481}
482
Marcel Holtmanndbece372014-07-04 18:11:55 +0200483static bool is_configured(struct hci_dev *hdev)
484{
485 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
486 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
487 return false;
488
489 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
490 !bacmp(&hdev->public_addr, BDADDR_ANY))
491 return false;
492
493 return true;
494}
495
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200496static __le32 get_missing_options(struct hci_dev *hdev)
497{
498 u32 options = 0;
499
Marcel Holtmanndbece372014-07-04 18:11:55 +0200500 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
501 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200502 options |= MGMT_OPTION_EXTERNAL_CONFIG;
503
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200504 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
505 !bacmp(&hdev->public_addr, BDADDR_ANY))
506 options |= MGMT_OPTION_PUBLIC_ADDRESS;
507
508 return cpu_to_le32(options);
509}
510
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200511static int new_options(struct hci_dev *hdev, struct sock *skip)
512{
513 __le32 options = get_missing_options(hdev);
514
515 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
516 sizeof(options), skip);
517}
518
Marcel Holtmanndbece372014-07-04 18:11:55 +0200519static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
520{
521 __le32 options = get_missing_options(hdev);
522
523 return cmd_complete(sk, hdev->id, opcode, 0, &options,
524 sizeof(options));
525}
526
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200527static int read_config_info(struct sock *sk, struct hci_dev *hdev,
528 void *data, u16 data_len)
529{
530 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200531 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200532
533 BT_DBG("sock %p %s", sk, hdev->name);
534
535 hci_dev_lock(hdev);
536
537 memset(&rp, 0, sizeof(rp));
538 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200539
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200540 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
541 options |= MGMT_OPTION_EXTERNAL_CONFIG;
542
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200543 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200544 options |= MGMT_OPTION_PUBLIC_ADDRESS;
545
546 rp.supported_options = cpu_to_le32(options);
547 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200548
549 hci_dev_unlock(hdev);
550
551 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
552 sizeof(rp));
553}
554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200556{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200557 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200558
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200559 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300560 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800561 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300562 settings |= MGMT_SETTING_CONNECTABLE;
563 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200564
Andre Guedesed3fa312012-07-24 15:03:46 -0300565 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500566 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
567 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200568 settings |= MGMT_SETTING_BREDR;
569 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700570
571 if (lmp_ssp_capable(hdev)) {
572 settings |= MGMT_SETTING_SSP;
573 settings |= MGMT_SETTING_HS;
574 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800575
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800576 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800577 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700578 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100579
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300580 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200581 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300582 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300583 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200584 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300585 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200586
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200587 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
588 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200589 settings |= MGMT_SETTING_CONFIGURATION;
590
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200591 return settings;
592}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200593
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200594static u32 get_current_settings(struct hci_dev *hdev)
595{
596 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200597
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200598 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100599 settings |= MGMT_SETTING_POWERED;
600
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200601 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200602 settings |= MGMT_SETTING_CONNECTABLE;
603
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500604 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
605 settings |= MGMT_SETTING_FAST_CONNECTABLE;
606
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200607 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200608 settings |= MGMT_SETTING_DISCOVERABLE;
609
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300610 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300611 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200612
Johan Hedberg56f87902013-10-02 13:43:13 +0300613 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614 settings |= MGMT_SETTING_BREDR;
615
Johan Hedberg06199cf2012-02-22 16:37:11 +0200616 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200618
Johan Hedberg47990ea2012-02-22 11:58:37 +0200619 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200620 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200621
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200622 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200623 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200624
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200625 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
626 settings |= MGMT_SETTING_HS;
627
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200628 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300629 settings |= MGMT_SETTING_ADVERTISING;
630
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800631 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
632 settings |= MGMT_SETTING_SECURE_CONN;
633
Johan Hedberg0663b292014-06-24 13:15:50 +0300634 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800635 settings |= MGMT_SETTING_DEBUG_KEYS;
636
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200637 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
638 settings |= MGMT_SETTING_PRIVACY;
639
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200640 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200641}
642
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300643#define PNP_INFO_SVCLASS_ID 0x1200
644
Johan Hedberg213202e2013-01-27 00:31:33 +0200645static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
646{
647 u8 *ptr = data, *uuids_start = NULL;
648 struct bt_uuid *uuid;
649
650 if (len < 4)
651 return ptr;
652
653 list_for_each_entry(uuid, &hdev->uuids, list) {
654 u16 uuid16;
655
656 if (uuid->size != 16)
657 continue;
658
659 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
660 if (uuid16 < 0x1100)
661 continue;
662
663 if (uuid16 == PNP_INFO_SVCLASS_ID)
664 continue;
665
666 if (!uuids_start) {
667 uuids_start = ptr;
668 uuids_start[0] = 1;
669 uuids_start[1] = EIR_UUID16_ALL;
670 ptr += 2;
671 }
672
673 /* Stop if not enough space to put next UUID */
674 if ((ptr - data) + sizeof(u16) > len) {
675 uuids_start[1] = EIR_UUID16_SOME;
676 break;
677 }
678
679 *ptr++ = (uuid16 & 0x00ff);
680 *ptr++ = (uuid16 & 0xff00) >> 8;
681 uuids_start[0] += sizeof(uuid16);
682 }
683
684 return ptr;
685}
686
Johan Hedbergcdf19632013-01-27 00:31:34 +0200687static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
688{
689 u8 *ptr = data, *uuids_start = NULL;
690 struct bt_uuid *uuid;
691
692 if (len < 6)
693 return ptr;
694
695 list_for_each_entry(uuid, &hdev->uuids, list) {
696 if (uuid->size != 32)
697 continue;
698
699 if (!uuids_start) {
700 uuids_start = ptr;
701 uuids_start[0] = 1;
702 uuids_start[1] = EIR_UUID32_ALL;
703 ptr += 2;
704 }
705
706 /* Stop if not enough space to put next UUID */
707 if ((ptr - data) + sizeof(u32) > len) {
708 uuids_start[1] = EIR_UUID32_SOME;
709 break;
710 }
711
712 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
713 ptr += sizeof(u32);
714 uuids_start[0] += sizeof(u32);
715 }
716
717 return ptr;
718}
719
Johan Hedbergc00d5752013-01-27 00:31:35 +0200720static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
721{
722 u8 *ptr = data, *uuids_start = NULL;
723 struct bt_uuid *uuid;
724
725 if (len < 18)
726 return ptr;
727
728 list_for_each_entry(uuid, &hdev->uuids, list) {
729 if (uuid->size != 128)
730 continue;
731
732 if (!uuids_start) {
733 uuids_start = ptr;
734 uuids_start[0] = 1;
735 uuids_start[1] = EIR_UUID128_ALL;
736 ptr += 2;
737 }
738
739 /* Stop if not enough space to put next UUID */
740 if ((ptr - data) + 16 > len) {
741 uuids_start[1] = EIR_UUID128_SOME;
742 break;
743 }
744
745 memcpy(ptr, uuid->uuid, 16);
746 ptr += 16;
747 uuids_start[0] += 16;
748 }
749
750 return ptr;
751}
752
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300753static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
754{
755 struct pending_cmd *cmd;
756
757 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
758 if (cmd->opcode == opcode)
759 return cmd;
760 }
761
762 return NULL;
763}
764
Johan Hedberg95868422014-06-28 17:54:07 +0300765static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
766 struct hci_dev *hdev,
767 const void *data)
768{
769 struct pending_cmd *cmd;
770
771 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
772 if (cmd->user_data != data)
773 continue;
774 if (cmd->opcode == opcode)
775 return cmd;
776 }
777
778 return NULL;
779}
780
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700781static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
782{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700783 u8 ad_len = 0;
784 size_t name_len;
785
786 name_len = strlen(hdev->dev_name);
787 if (name_len > 0) {
788 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
789
790 if (name_len > max_len) {
791 name_len = max_len;
792 ptr[1] = EIR_NAME_SHORT;
793 } else
794 ptr[1] = EIR_NAME_COMPLETE;
795
796 ptr[0] = name_len + 1;
797
798 memcpy(ptr + 2, hdev->dev_name, name_len);
799
800 ad_len += (name_len + 2);
801 ptr += (name_len + 2);
802 }
803
804 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700805}
806
807static void update_scan_rsp_data(struct hci_request *req)
808{
809 struct hci_dev *hdev = req->hdev;
810 struct hci_cp_le_set_scan_rsp_data cp;
811 u8 len;
812
Johan Hedberg7751ef12013-10-19 23:38:15 +0300813 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700814 return;
815
816 memset(&cp, 0, sizeof(cp));
817
818 len = create_scan_rsp_data(hdev, cp.data);
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 if (hdev->scan_rsp_data_len == len &&
821 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822 return;
823
Johan Hedbergeb438b52013-10-16 15:31:07 +0300824 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
825 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700826
827 cp.length = len;
828
829 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
830}
831
Johan Hedberg9a43e252013-10-20 19:00:07 +0300832static u8 get_adv_discov_flags(struct hci_dev *hdev)
833{
834 struct pending_cmd *cmd;
835
836 /* If there's a pending mgmt command the flags will not yet have
837 * their final values, so check for this first.
838 */
839 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
840 if (cmd) {
841 struct mgmt_mode *cp = cmd->param;
842 if (cp->val == 0x01)
843 return LE_AD_GENERAL;
844 else if (cp->val == 0x02)
845 return LE_AD_LIMITED;
846 } else {
847 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
848 return LE_AD_LIMITED;
849 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
850 return LE_AD_GENERAL;
851 }
852
853 return 0;
854}
855
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700856static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857{
858 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859
Johan Hedberg9a43e252013-10-20 19:00:07 +0300860 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700861
Johan Hedberge8340042014-01-30 11:16:50 -0800862 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700863 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700864
865 if (flags) {
866 BT_DBG("adv flags 0x%02x", flags);
867
868 ptr[0] = 2;
869 ptr[1] = EIR_FLAGS;
870 ptr[2] = flags;
871
872 ad_len += 3;
873 ptr += 3;
874 }
875
876 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
877 ptr[0] = 2;
878 ptr[1] = EIR_TX_POWER;
879 ptr[2] = (u8) hdev->adv_tx_power;
880
881 ad_len += 3;
882 ptr += 3;
883 }
884
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885 return ad_len;
886}
887
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700888static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700889{
890 struct hci_dev *hdev = req->hdev;
891 struct hci_cp_le_set_adv_data cp;
892 u8 len;
893
Johan Hedberg10994ce2013-10-19 23:38:16 +0300894 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700895 return;
896
897 memset(&cp, 0, sizeof(cp));
898
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700899 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700900
901 if (hdev->adv_data_len == len &&
902 memcmp(cp.data, hdev->adv_data, len) == 0)
903 return;
904
905 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
906 hdev->adv_data_len = len;
907
908 cp.length = len;
909
910 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
911}
912
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300913int mgmt_update_adv_data(struct hci_dev *hdev)
914{
915 struct hci_request req;
916
917 hci_req_init(&req, hdev);
918 update_adv_data(&req);
919
920 return hci_req_run(&req, NULL);
921}
922
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300923static void create_eir(struct hci_dev *hdev, u8 *data)
924{
925 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300926 size_t name_len;
927
928 name_len = strlen(hdev->dev_name);
929
930 if (name_len > 0) {
931 /* EIR Data type */
932 if (name_len > 48) {
933 name_len = 48;
934 ptr[1] = EIR_NAME_SHORT;
935 } else
936 ptr[1] = EIR_NAME_COMPLETE;
937
938 /* EIR Data length */
939 ptr[0] = name_len + 1;
940
941 memcpy(ptr + 2, hdev->dev_name, name_len);
942
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300943 ptr += (name_len + 2);
944 }
945
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100946 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700947 ptr[0] = 2;
948 ptr[1] = EIR_TX_POWER;
949 ptr[2] = (u8) hdev->inq_tx_power;
950
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700951 ptr += 3;
952 }
953
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700954 if (hdev->devid_source > 0) {
955 ptr[0] = 9;
956 ptr[1] = EIR_DEVICE_ID;
957
958 put_unaligned_le16(hdev->devid_source, ptr + 2);
959 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
960 put_unaligned_le16(hdev->devid_product, ptr + 6);
961 put_unaligned_le16(hdev->devid_version, ptr + 8);
962
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700963 ptr += 10;
964 }
965
Johan Hedberg213202e2013-01-27 00:31:33 +0200966 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200967 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200968 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300969}
970
Johan Hedberg890ea892013-03-15 17:06:52 -0500971static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300972{
Johan Hedberg890ea892013-03-15 17:06:52 -0500973 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300974 struct hci_cp_write_eir cp;
975
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200976 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500977 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200978
Johan Hedberg976eb202012-10-24 21:12:01 +0300979 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200982 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200985 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500986 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300987
988 memset(&cp, 0, sizeof(cp));
989
990 create_eir(hdev, cp.data);
991
992 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500993 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300994
995 memcpy(hdev->eir, cp.data, sizeof(cp.data));
996
Johan Hedberg890ea892013-03-15 17:06:52 -0500997 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300998}
999
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000static u8 get_service_classes(struct hci_dev *hdev)
1001{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001002 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003 u8 val = 0;
1004
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001005 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001006 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001007
1008 return val;
1009}
1010
Johan Hedberg890ea892013-03-15 17:06:52 -05001011static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001012{
Johan Hedberg890ea892013-03-15 17:06:52 -05001013 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001014 u8 cod[3];
1015
1016 BT_DBG("%s", hdev->name);
1017
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001018 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001019 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001020
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001021 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1022 return;
1023
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001024 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001025 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001026
1027 cod[0] = hdev->minor_class;
1028 cod[1] = hdev->major_class;
1029 cod[2] = get_service_classes(hdev);
1030
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001031 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1032 cod[1] |= 0x20;
1033
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001034 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001035 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001036
Johan Hedberg890ea892013-03-15 17:06:52 -05001037 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001038}
1039
Johan Hedberga4858cb2014-02-25 19:56:31 +02001040static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001041{
1042 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001043
1044 /* If there's a pending mgmt command the flag will not yet have
1045 * it's final value, so check for this first.
1046 */
1047 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1048 if (cmd) {
1049 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001050 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001051 }
1052
Johan Hedberga4858cb2014-02-25 19:56:31 +02001053 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001054}
1055
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001056static void disable_advertising(struct hci_request *req)
1057{
1058 u8 enable = 0x00;
1059
1060 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1061}
1062
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001063static void enable_advertising(struct hci_request *req)
1064{
1065 struct hci_dev *hdev = req->hdev;
1066 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001067 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001068 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001069
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001070 if (hci_conn_num(hdev, LE_LINK) > 0)
1071 return;
1072
1073 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1074 disable_advertising(req);
1075
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001076 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001077 * hci_update_random_address knows that it's safe to go ahead
1078 * and write a new random address. The flag will be set back on
1079 * as soon as the SET_ADV_ENABLE HCI command completes.
1080 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001081 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001082
Johan Hedberga4858cb2014-02-25 19:56:31 +02001083 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001084
Johan Hedberga4858cb2014-02-25 19:56:31 +02001085 /* Set require_privacy to true only when non-connectable
1086 * advertising is used. In that case it is fine to use a
1087 * non-resolvable private address.
1088 */
1089 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001090 return;
1091
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001092 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001093 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1094 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001095 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001096 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001097 cp.channel_map = hdev->le_adv_channel_map;
1098
1099 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1100
1101 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1102}
1103
Johan Hedberg7d785252011-12-15 00:47:39 +02001104static void service_cache_off(struct work_struct *work)
1105{
1106 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001107 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001108 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001109
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001110 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001111 return;
1112
Johan Hedberg890ea892013-03-15 17:06:52 -05001113 hci_req_init(&req, hdev);
1114
Johan Hedberg7d785252011-12-15 00:47:39 +02001115 hci_dev_lock(hdev);
1116
Johan Hedberg890ea892013-03-15 17:06:52 -05001117 update_eir(&req);
1118 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001119
1120 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001121
1122 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001123}
1124
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001125static void rpa_expired(struct work_struct *work)
1126{
1127 struct hci_dev *hdev = container_of(work, struct hci_dev,
1128 rpa_expired.work);
1129 struct hci_request req;
1130
1131 BT_DBG("");
1132
1133 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1134
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001135 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001136 return;
1137
1138 /* The generation of a new RPA and programming it into the
1139 * controller happens in the enable_advertising() function.
1140 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001141 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001142 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001143 hci_req_run(&req, NULL);
1144}
1145
Johan Hedberg6a919082012-02-28 06:17:26 +02001146static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001147{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001148 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001149 return;
1150
Johan Hedberg4f87da82012-03-02 19:55:56 +02001151 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001152 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001153
Johan Hedberg4f87da82012-03-02 19:55:56 +02001154 /* Non-mgmt controlled devices get this bit set
1155 * implicitly so that pairing works for them, however
1156 * for mgmt we require user-space to explicitly enable
1157 * it
1158 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001159 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001160}
1161
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001162static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001163 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001164{
1165 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001166
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001167 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001168
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001169 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001170
Johan Hedberg03811012010-12-08 00:21:06 +02001171 memset(&rp, 0, sizeof(rp));
1172
Johan Hedberg03811012010-12-08 00:21:06 +02001173 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001174
1175 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001176 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001177
1178 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1179 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1180
1181 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001182
1183 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001184 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001185
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001186 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001188 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001189 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001190}
1191
1192static void mgmt_pending_free(struct pending_cmd *cmd)
1193{
1194 sock_put(cmd->sk);
1195 kfree(cmd->param);
1196 kfree(cmd);
1197}
1198
1199static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001200 struct hci_dev *hdev, void *data,
1201 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001202{
1203 struct pending_cmd *cmd;
1204
Johan Hedbergfca20012014-06-28 17:54:05 +03001205 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001206 if (!cmd)
1207 return NULL;
1208
1209 cmd->opcode = opcode;
1210 cmd->index = hdev->id;
1211
Johan Hedberg323b0b82014-12-05 13:36:01 +02001212 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001213 if (!cmd->param) {
1214 kfree(cmd);
1215 return NULL;
1216 }
1217
Johan Hedberg323b0b82014-12-05 13:36:01 +02001218 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001219
1220 cmd->sk = sk;
1221 sock_hold(sk);
1222
1223 list_add(&cmd->list, &hdev->mgmt_pending);
1224
1225 return cmd;
1226}
1227
1228static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001229 void (*cb)(struct pending_cmd *cmd,
1230 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001231 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001232{
Andre Guedesa3d09352013-02-01 11:21:30 -03001233 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001234
Andre Guedesa3d09352013-02-01 11:21:30 -03001235 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001236 if (opcode > 0 && cmd->opcode != opcode)
1237 continue;
1238
1239 cb(cmd, data);
1240 }
1241}
1242
Johan Hedberg03811012010-12-08 00:21:06 +02001243static void mgmt_pending_remove(struct pending_cmd *cmd)
1244{
1245 list_del(&cmd->list);
1246 mgmt_pending_free(cmd);
1247}
1248
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001249static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001250{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001251 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001252
Johan Hedbergaee9b212012-02-18 15:07:59 +02001253 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001254 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001255}
1256
Marcel Holtmann1904a852015-01-11 13:50:44 -08001257static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001258{
1259 BT_DBG("%s status 0x%02x", hdev->name, status);
1260
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 if (hci_conn_count(hdev) == 0) {
1262 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001263 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001264 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001265}
1266
Johan Hedberg23a48092014-07-08 16:05:06 +03001267static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001268{
1269 struct hci_dev *hdev = req->hdev;
1270 struct hci_cp_remote_name_req_cancel cp;
1271 struct inquiry_entry *e;
1272
1273 switch (hdev->discovery.state) {
1274 case DISCOVERY_FINDING:
1275 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1276 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1277 } else {
1278 cancel_delayed_work(&hdev->le_scan_disable);
1279 hci_req_add_le_scan_disable(req);
1280 }
1281
Johan Hedberg23a48092014-07-08 16:05:06 +03001282 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001283
1284 case DISCOVERY_RESOLVING:
1285 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1286 NAME_PENDING);
1287 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001288 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001289
1290 bacpy(&cp.bdaddr, &e->data.bdaddr);
1291 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1292 &cp);
1293
Johan Hedberg23a48092014-07-08 16:05:06 +03001294 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001295
1296 default:
1297 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001298 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001299 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001300 return true;
1301 }
1302
Johan Hedberg21a60d32014-06-10 14:05:58 +03001303 break;
1304 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001305
1306 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001307}
1308
Johan Hedberg8b064a32014-02-24 14:52:22 +02001309static int clean_up_hci_state(struct hci_dev *hdev)
1310{
1311 struct hci_request req;
1312 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001313 bool discov_stopped;
1314 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001315
1316 hci_req_init(&req, hdev);
1317
1318 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1319 test_bit(HCI_PSCAN, &hdev->flags)) {
1320 u8 scan = 0x00;
1321 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1322 }
1323
Johan Hedberg73e082f2014-07-08 15:07:51 +03001324 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325 disable_advertising(&req);
1326
Johan Hedberg23a48092014-07-08 16:05:06 +03001327 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001328
1329 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1330 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001331 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001332
Johan Hedbergc9910d02014-02-27 14:35:12 +02001333 switch (conn->state) {
1334 case BT_CONNECTED:
1335 case BT_CONFIG:
1336 dc.handle = cpu_to_le16(conn->handle);
1337 dc.reason = 0x15; /* Terminated due to Power Off */
1338 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1339 break;
1340 case BT_CONNECT:
1341 if (conn->type == LE_LINK)
1342 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1343 0, NULL);
1344 else if (conn->type == ACL_LINK)
1345 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1346 6, &conn->dst);
1347 break;
1348 case BT_CONNECT2:
1349 bacpy(&rej.bdaddr, &conn->dst);
1350 rej.reason = 0x15; /* Terminated due to Power Off */
1351 if (conn->type == ACL_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1353 sizeof(rej), &rej);
1354 else if (conn->type == SCO_LINK)
1355 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1356 sizeof(rej), &rej);
1357 break;
1358 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001359 }
1360
Johan Hedberg23a48092014-07-08 16:05:06 +03001361 err = hci_req_run(&req, clean_up_hci_complete);
1362 if (!err && discov_stopped)
1363 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1364
1365 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001366}
1367
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001368static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001369 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001370{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001371 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001372 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001373 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001374
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001375 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001376
Johan Hedberga7e80f22013-01-09 16:05:19 +02001377 if (cp->val != 0x00 && cp->val != 0x01)
1378 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1379 MGMT_STATUS_INVALID_PARAMS);
1380
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001381 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001382
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001383 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1384 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1385 MGMT_STATUS_BUSY);
1386 goto failed;
1387 }
1388
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001389 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1390 cancel_delayed_work(&hdev->power_off);
1391
1392 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001393 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1394 data, len);
1395 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001396 goto failed;
1397 }
1398 }
1399
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001400 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001401 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001402 goto failed;
1403 }
1404
Johan Hedberg03811012010-12-08 00:21:06 +02001405 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1406 if (!cmd) {
1407 err = -ENOMEM;
1408 goto failed;
1409 }
1410
Johan Hedberg8b064a32014-02-24 14:52:22 +02001411 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001412 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001413 err = 0;
1414 } else {
1415 /* Disconnect connections, stop scans, etc */
1416 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001417 if (!err)
1418 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1419 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001420
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 /* ENODATA means there were no HCI commands queued */
1422 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001423 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001424 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1425 err = 0;
1426 }
1427 }
Johan Hedberg03811012010-12-08 00:21:06 +02001428
1429failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001430 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001431 return err;
1432}
1433
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001434static int new_settings(struct hci_dev *hdev, struct sock *skip)
1435{
1436 __le32 ev;
1437
1438 ev = cpu_to_le32(get_current_settings(hdev));
1439
1440 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1441}
1442
Johan Hedberg91a668b2014-07-09 13:28:26 +03001443int mgmt_new_settings(struct hci_dev *hdev)
1444{
1445 return new_settings(hdev, NULL);
1446}
1447
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001448struct cmd_lookup {
1449 struct sock *sk;
1450 struct hci_dev *hdev;
1451 u8 mgmt_status;
1452};
1453
1454static void settings_rsp(struct pending_cmd *cmd, void *data)
1455{
1456 struct cmd_lookup *match = data;
1457
1458 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1459
1460 list_del(&cmd->list);
1461
1462 if (match->sk == NULL) {
1463 match->sk = cmd->sk;
1464 sock_hold(match->sk);
1465 }
1466
1467 mgmt_pending_free(cmd);
1468}
1469
1470static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1471{
1472 u8 *status = data;
1473
1474 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1475 mgmt_pending_remove(cmd);
1476}
1477
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001478static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1479{
1480 if (cmd->cmd_complete) {
1481 u8 *status = data;
1482
1483 cmd->cmd_complete(cmd, *status);
1484 mgmt_pending_remove(cmd);
1485
1486 return;
1487 }
1488
1489 cmd_status_rsp(cmd, data);
1490}
1491
Johan Hedberg9df74652014-12-19 22:26:03 +02001492static int generic_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001493{
Johan Hedberg9df74652014-12-19 22:26:03 +02001494 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1495 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001496}
1497
Johan Hedberg9df74652014-12-19 22:26:03 +02001498static int addr_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001499{
Johan Hedberg9df74652014-12-19 22:26:03 +02001500 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1501 sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001502}
1503
Johan Hedberge6fe7982013-10-02 15:45:22 +03001504static u8 mgmt_bredr_support(struct hci_dev *hdev)
1505{
1506 if (!lmp_bredr_capable(hdev))
1507 return MGMT_STATUS_NOT_SUPPORTED;
1508 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1509 return MGMT_STATUS_REJECTED;
1510 else
1511 return MGMT_STATUS_SUCCESS;
1512}
1513
1514static u8 mgmt_le_support(struct hci_dev *hdev)
1515{
1516 if (!lmp_le_capable(hdev))
1517 return MGMT_STATUS_NOT_SUPPORTED;
1518 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1519 return MGMT_STATUS_REJECTED;
1520 else
1521 return MGMT_STATUS_SUCCESS;
1522}
1523
Marcel Holtmann1904a852015-01-11 13:50:44 -08001524static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1525 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526{
1527 struct pending_cmd *cmd;
1528 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001529 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001530 bool changed;
1531
1532 BT_DBG("status 0x%02x", status);
1533
1534 hci_dev_lock(hdev);
1535
1536 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1537 if (!cmd)
1538 goto unlock;
1539
1540 if (status) {
1541 u8 mgmt_err = mgmt_status(status);
1542 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001543 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001544 goto remove_cmd;
1545 }
1546
1547 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001548 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001549 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1550 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001551
1552 if (hdev->discov_timeout > 0) {
1553 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1554 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1555 to);
1556 }
1557 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001558 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1559 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001560 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001561
1562 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1563
1564 if (changed)
1565 new_settings(hdev, cmd->sk);
1566
Marcel Holtmann970ba522013-10-15 06:33:57 -07001567 /* When the discoverable mode gets changed, make sure
1568 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001569 * bit correctly set. Also update page scan based on whitelist
1570 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001571 */
1572 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001573 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001574 update_class(&req);
1575 hci_req_run(&req, NULL);
1576
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001577remove_cmd:
1578 mgmt_pending_remove(cmd);
1579
1580unlock:
1581 hci_dev_unlock(hdev);
1582}
1583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001584static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001585 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001586{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001587 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001588 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001589 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001590 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001591 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001592 int err;
1593
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001594 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001595
Johan Hedberg9a43e252013-10-20 19:00:07 +03001596 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1597 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001598 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001599 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001600
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001601 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001602 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1603 MGMT_STATUS_INVALID_PARAMS);
1604
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001605 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001606
1607 /* Disabling discoverable requires that no timeout is set,
1608 * and enabling limited discoverable requires a timeout.
1609 */
1610 if ((cp->val == 0x00 && timeout > 0) ||
1611 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001612 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001613 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001614
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001615 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001616
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001617 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001618 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001619 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001620 goto failed;
1621 }
1622
1623 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001624 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001625 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001626 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001627 goto failed;
1628 }
1629
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001630 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001631 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001632 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001633 goto failed;
1634 }
1635
1636 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001637 bool changed = false;
1638
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001639 /* Setting limited discoverable when powered off is
1640 * not a valid operation since it requires a timeout
1641 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1642 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001643 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1644 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1645 changed = true;
1646 }
1647
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001648 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001649 if (err < 0)
1650 goto failed;
1651
1652 if (changed)
1653 err = new_settings(hdev, sk);
1654
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001655 goto failed;
1656 }
1657
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001658 /* If the current mode is the same, then just update the timeout
1659 * value with the new value. And if only the timeout gets updated,
1660 * then no need for any HCI transactions.
1661 */
1662 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1663 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1664 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001665 cancel_delayed_work(&hdev->discov_off);
1666 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001667
Marcel Holtmann36261542013-10-15 08:28:51 -07001668 if (cp->val && hdev->discov_timeout > 0) {
1669 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001670 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001671 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001672 }
1673
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001674 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001675 goto failed;
1676 }
1677
1678 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1679 if (!cmd) {
1680 err = -ENOMEM;
1681 goto failed;
1682 }
1683
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001684 /* Cancel any potential discoverable timeout that might be
1685 * still active and store new timeout value. The arming of
1686 * the timeout happens in the complete handler.
1687 */
1688 cancel_delayed_work(&hdev->discov_off);
1689 hdev->discov_timeout = timeout;
1690
Johan Hedbergb456f872013-10-19 23:38:22 +03001691 /* Limited discoverable mode */
1692 if (cp->val == 0x02)
1693 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1694 else
1695 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1696
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001697 hci_req_init(&req, hdev);
1698
Johan Hedberg9a43e252013-10-20 19:00:07 +03001699 /* The procedure for LE-only controllers is much simpler - just
1700 * update the advertising data.
1701 */
1702 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1703 goto update_ad;
1704
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001705 scan = SCAN_PAGE;
1706
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001707 if (cp->val) {
1708 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001709
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001710 if (cp->val == 0x02) {
1711 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001712 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001713 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1714 hci_cp.iac_lap[1] = 0x8b;
1715 hci_cp.iac_lap[2] = 0x9e;
1716 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1717 hci_cp.iac_lap[4] = 0x8b;
1718 hci_cp.iac_lap[5] = 0x9e;
1719 } else {
1720 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001721 hci_cp.num_iac = 1;
1722 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1723 hci_cp.iac_lap[1] = 0x8b;
1724 hci_cp.iac_lap[2] = 0x9e;
1725 }
1726
1727 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1728 (hci_cp.num_iac * 3) + 1, &hci_cp);
1729
1730 scan |= SCAN_INQUIRY;
1731 } else {
1732 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1733 }
1734
1735 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001736
Johan Hedberg9a43e252013-10-20 19:00:07 +03001737update_ad:
1738 update_adv_data(&req);
1739
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001740 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001741 if (err < 0)
1742 mgmt_pending_remove(cmd);
1743
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001744failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001745 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001746 return err;
1747}
1748
Johan Hedberg406d7802013-03-15 17:07:09 -05001749static void write_fast_connectable(struct hci_request *req, bool enable)
1750{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001751 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001752 struct hci_cp_write_page_scan_activity acp;
1753 u8 type;
1754
Johan Hedberg547003b2013-10-21 16:51:53 +03001755 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1756 return;
1757
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001758 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1759 return;
1760
Johan Hedberg406d7802013-03-15 17:07:09 -05001761 if (enable) {
1762 type = PAGE_SCAN_TYPE_INTERLACED;
1763
1764 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001765 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001766 } else {
1767 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1768
1769 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001770 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001771 }
1772
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001773 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001774
Johan Hedbergbd98b992013-03-15 17:07:13 -05001775 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1776 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1777 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1778 sizeof(acp), &acp);
1779
1780 if (hdev->page_scan_type != type)
1781 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001782}
1783
Marcel Holtmann1904a852015-01-11 13:50:44 -08001784static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1785 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001786{
1787 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001788 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001789 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001790
1791 BT_DBG("status 0x%02x", status);
1792
1793 hci_dev_lock(hdev);
1794
1795 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1796 if (!cmd)
1797 goto unlock;
1798
Johan Hedberg37438c12013-10-14 16:20:05 +03001799 if (status) {
1800 u8 mgmt_err = mgmt_status(status);
1801 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1802 goto remove_cmd;
1803 }
1804
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001805 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001806 if (cp->val) {
1807 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1808 &hdev->dev_flags);
1809 discov_changed = false;
1810 } else {
1811 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1812 &hdev->dev_flags);
1813 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1814 &hdev->dev_flags);
1815 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001816
Johan Hedberg2b76f452013-03-15 17:07:04 -05001817 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1818
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001819 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001820 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001821 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001822 if (discov_changed)
1823 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001824 hci_update_background_scan(hdev);
1825 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001826
Johan Hedberg37438c12013-10-14 16:20:05 +03001827remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001828 mgmt_pending_remove(cmd);
1829
1830unlock:
1831 hci_dev_unlock(hdev);
1832}
1833
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001834static int set_connectable_update_settings(struct hci_dev *hdev,
1835 struct sock *sk, u8 val)
1836{
1837 bool changed = false;
1838 int err;
1839
1840 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1841 changed = true;
1842
1843 if (val) {
1844 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1845 } else {
1846 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1847 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1848 }
1849
1850 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1851 if (err < 0)
1852 return err;
1853
Johan Hedberg562064e2014-07-08 16:35:34 +03001854 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001855 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001856 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001857 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001858 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001859
1860 return 0;
1861}
1862
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001863static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001864 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001865{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001866 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001867 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001868 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001870 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001871
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001872 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001873
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001874 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1875 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001876 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001877 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001878
Johan Hedberga7e80f22013-01-09 16:05:19 +02001879 if (cp->val != 0x00 && cp->val != 0x01)
1880 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1881 MGMT_STATUS_INVALID_PARAMS);
1882
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001883 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001884
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001885 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001886 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001887 goto failed;
1888 }
1889
1890 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001891 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001892 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001893 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001894 goto failed;
1895 }
1896
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001897 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1898 if (!cmd) {
1899 err = -ENOMEM;
1900 goto failed;
1901 }
1902
Johan Hedberg2b76f452013-03-15 17:07:04 -05001903 hci_req_init(&req, hdev);
1904
Johan Hedberg9a43e252013-10-20 19:00:07 +03001905 /* If BR/EDR is not enabled and we disable advertising as a
1906 * by-product of disabling connectable, we need to update the
1907 * advertising flags.
1908 */
1909 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1910 if (!cp->val) {
1911 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1912 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1913 }
1914 update_adv_data(&req);
1915 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001916 if (cp->val) {
1917 scan = SCAN_PAGE;
1918 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001919 /* If we don't have any whitelist entries just
1920 * disable all scanning. If there are entries
1921 * and we had both page and inquiry scanning
1922 * enabled then fall back to only page scanning.
1923 * Otherwise no changes are needed.
1924 */
1925 if (list_empty(&hdev->whitelist))
1926 scan = SCAN_DISABLED;
1927 else if (test_bit(HCI_ISCAN, &hdev->flags))
1928 scan = SCAN_PAGE;
1929 else
1930 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001931
1932 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001933 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001934 cancel_delayed_work(&hdev->discov_off);
1935 }
1936
1937 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1938 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001939
Johan Hedberg3bd27242014-07-28 20:53:58 +03001940no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001941 /* If we're going from non-connectable to connectable or
1942 * vice-versa when fast connectable is enabled ensure that fast
1943 * connectable gets disabled. write_fast_connectable won't do
1944 * anything if the page scan parameters are already what they
1945 * should be.
1946 */
1947 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001948 write_fast_connectable(&req, false);
1949
Johan Hedberge8b12022014-07-10 10:51:27 +03001950 /* Update the advertising parameters if necessary */
1951 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001952 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001953
Johan Hedberg2b76f452013-03-15 17:07:04 -05001954 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001956 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001957 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001958 err = set_connectable_update_settings(hdev, sk,
1959 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001960 goto failed;
1961 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001962
1963failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001964 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001965 return err;
1966}
1967
Johan Hedbergb2939472014-07-30 09:22:23 +03001968static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001969 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001970{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001971 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001972 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001973 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001974
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001975 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001976
Johan Hedberga7e80f22013-01-09 16:05:19 +02001977 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001978 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001979 MGMT_STATUS_INVALID_PARAMS);
1980
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001981 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982
1983 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001984 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001985 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001986 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001987
Johan Hedbergb2939472014-07-30 09:22:23 +03001988 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001990 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001991
Marcel Holtmann55594352013-10-06 16:11:57 -07001992 if (changed)
1993 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001994
Marcel Holtmann55594352013-10-06 16:11:57 -07001995unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001996 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001997 return err;
1998}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001999
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002000static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2001 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002002{
2003 struct mgmt_mode *cp = data;
2004 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002005 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002006 int err;
2007
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002008 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002009
Johan Hedberge6fe7982013-10-02 15:45:22 +03002010 status = mgmt_bredr_support(hdev);
2011 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002012 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002013 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002014
Johan Hedberga7e80f22013-01-09 16:05:19 +02002015 if (cp->val != 0x00 && cp->val != 0x01)
2016 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2017 MGMT_STATUS_INVALID_PARAMS);
2018
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002019 hci_dev_lock(hdev);
2020
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002021 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002022 bool changed = false;
2023
2024 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002025 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002026 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2027 changed = true;
2028 }
2029
2030 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2031 if (err < 0)
2032 goto failed;
2033
2034 if (changed)
2035 err = new_settings(hdev, sk);
2036
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002037 goto failed;
2038 }
2039
2040 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002041 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002042 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002043 goto failed;
2044 }
2045
2046 val = !!cp->val;
2047
2048 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2049 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2050 goto failed;
2051 }
2052
2053 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2054 if (!cmd) {
2055 err = -ENOMEM;
2056 goto failed;
2057 }
2058
2059 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2060 if (err < 0) {
2061 mgmt_pending_remove(cmd);
2062 goto failed;
2063 }
2064
2065failed:
2066 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002067 return err;
2068}
2069
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002070static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002071{
2072 struct mgmt_mode *cp = data;
2073 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002074 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002075 int err;
2076
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002077 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002078
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002079 status = mgmt_bredr_support(hdev);
2080 if (status)
2081 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2082
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002083 if (!lmp_ssp_capable(hdev))
2084 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2085 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002086
Johan Hedberga7e80f22013-01-09 16:05:19 +02002087 if (cp->val != 0x00 && cp->val != 0x01)
2088 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2089 MGMT_STATUS_INVALID_PARAMS);
2090
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002091 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002092
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002093 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002094 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002095
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002096 if (cp->val) {
2097 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2098 &hdev->dev_flags);
2099 } else {
2100 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2101 &hdev->dev_flags);
2102 if (!changed)
2103 changed = test_and_clear_bit(HCI_HS_ENABLED,
2104 &hdev->dev_flags);
2105 else
2106 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002107 }
2108
2109 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2110 if (err < 0)
2111 goto failed;
2112
2113 if (changed)
2114 err = new_settings(hdev, sk);
2115
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002116 goto failed;
2117 }
2118
Johan Hedberg94d52da2015-02-19 17:38:06 +02002119 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002120 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2121 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002122 goto failed;
2123 }
2124
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002125 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002126 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2127 goto failed;
2128 }
2129
2130 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2131 if (!cmd) {
2132 err = -ENOMEM;
2133 goto failed;
2134 }
2135
Johan Hedberg37699722014-06-24 14:00:27 +03002136 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2137 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2138 sizeof(cp->val), &cp->val);
2139
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002140 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002141 if (err < 0) {
2142 mgmt_pending_remove(cmd);
2143 goto failed;
2144 }
2145
2146failed:
2147 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002148 return err;
2149}
2150
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002151static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002152{
2153 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002154 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002155 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002156 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002158 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002159
Johan Hedberge6fe7982013-10-02 15:45:22 +03002160 status = mgmt_bredr_support(hdev);
2161 if (status)
2162 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002163
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002164 if (!lmp_ssp_capable(hdev))
2165 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2166 MGMT_STATUS_NOT_SUPPORTED);
2167
2168 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2170 MGMT_STATUS_REJECTED);
2171
Johan Hedberga7e80f22013-01-09 16:05:19 +02002172 if (cp->val != 0x00 && cp->val != 0x01)
2173 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2174 MGMT_STATUS_INVALID_PARAMS);
2175
Marcel Holtmannee392692013-10-01 22:59:23 -07002176 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002177
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002178 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002179 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002180 } else {
2181 if (hdev_is_powered(hdev)) {
2182 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2183 MGMT_STATUS_REJECTED);
2184 goto unlock;
2185 }
2186
Marcel Holtmannee392692013-10-01 22:59:23 -07002187 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002188 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002189
2190 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2191 if (err < 0)
2192 goto unlock;
2193
2194 if (changed)
2195 err = new_settings(hdev, sk);
2196
2197unlock:
2198 hci_dev_unlock(hdev);
2199 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002200}
2201
Marcel Holtmann1904a852015-01-11 13:50:44 -08002202static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002203{
2204 struct cmd_lookup match = { NULL, hdev };
2205
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302206 hci_dev_lock(hdev);
2207
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002208 if (status) {
2209 u8 mgmt_err = mgmt_status(status);
2210
2211 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2212 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302213 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002214 }
2215
2216 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2217
2218 new_settings(hdev, match.sk);
2219
2220 if (match.sk)
2221 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002222
2223 /* Make sure the controller has a good default for
2224 * advertising data. Restrict the update to when LE
2225 * has actually been enabled. During power on, the
2226 * update in powered_update_hci will take care of it.
2227 */
2228 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2229 struct hci_request req;
2230
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002231 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002232 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002233 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002234 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002235 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002236 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302237
2238unlock:
2239 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002240}
2241
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002242static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002243{
2244 struct mgmt_mode *cp = data;
2245 struct hci_cp_write_le_host_supported hci_cp;
2246 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002247 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002249 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002250
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002251 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002252
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002253 if (!lmp_le_capable(hdev))
2254 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2255 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002256
Johan Hedberga7e80f22013-01-09 16:05:19 +02002257 if (cp->val != 0x00 && cp->val != 0x01)
2258 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2259 MGMT_STATUS_INVALID_PARAMS);
2260
Johan Hedbergc73eee92013-04-19 18:35:21 +03002261 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002262 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002263 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2264 MGMT_STATUS_REJECTED);
2265
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002266 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002267
2268 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002269 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002270
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002271 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002272 bool changed = false;
2273
2274 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2275 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2276 changed = true;
2277 }
2278
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002279 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2280 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002281 changed = true;
2282 }
2283
Johan Hedberg06199cf2012-02-22 16:37:11 +02002284 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2285 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002286 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002287
2288 if (changed)
2289 err = new_settings(hdev, sk);
2290
Johan Hedberg1de028c2012-02-29 19:55:35 -08002291 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002292 }
2293
Johan Hedberg4375f102013-09-25 13:26:10 +03002294 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2295 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002296 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002297 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002298 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299 }
2300
2301 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2302 if (!cmd) {
2303 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002304 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002305 }
2306
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002307 hci_req_init(&req, hdev);
2308
Johan Hedberg06199cf2012-02-22 16:37:11 +02002309 memset(&hci_cp, 0, sizeof(hci_cp));
2310
2311 if (val) {
2312 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002313 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002314 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002315 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002316 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002317 }
2318
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002319 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2320 &hci_cp);
2321
2322 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302323 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002325
Johan Hedberg1de028c2012-02-29 19:55:35 -08002326unlock:
2327 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002328 return err;
2329}
2330
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002331/* This is a helper function to test for pending mgmt commands that can
2332 * cause CoD or EIR HCI commands. We can only allow one such pending
2333 * mgmt command at a time since otherwise we cannot easily track what
2334 * the current values are, will be, and based on that calculate if a new
2335 * HCI command needs to be sent and if yes with what value.
2336 */
2337static bool pending_eir_or_class(struct hci_dev *hdev)
2338{
2339 struct pending_cmd *cmd;
2340
2341 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2342 switch (cmd->opcode) {
2343 case MGMT_OP_ADD_UUID:
2344 case MGMT_OP_REMOVE_UUID:
2345 case MGMT_OP_SET_DEV_CLASS:
2346 case MGMT_OP_SET_POWERED:
2347 return true;
2348 }
2349 }
2350
2351 return false;
2352}
2353
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002354static const u8 bluetooth_base_uuid[] = {
2355 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2356 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2357};
2358
2359static u8 get_uuid_size(const u8 *uuid)
2360{
2361 u32 val;
2362
2363 if (memcmp(uuid, bluetooth_base_uuid, 12))
2364 return 128;
2365
2366 val = get_unaligned_le32(&uuid[12]);
2367 if (val > 0xffff)
2368 return 32;
2369
2370 return 16;
2371}
2372
Johan Hedberg92da6092013-03-15 17:06:55 -05002373static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2374{
2375 struct pending_cmd *cmd;
2376
2377 hci_dev_lock(hdev);
2378
2379 cmd = mgmt_pending_find(mgmt_op, hdev);
2380 if (!cmd)
2381 goto unlock;
2382
2383 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2384 hdev->dev_class, 3);
2385
2386 mgmt_pending_remove(cmd);
2387
2388unlock:
2389 hci_dev_unlock(hdev);
2390}
2391
Marcel Holtmann1904a852015-01-11 13:50:44 -08002392static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002393{
2394 BT_DBG("status 0x%02x", status);
2395
2396 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2397}
2398
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002399static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002400{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002401 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002402 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002403 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002405 int err;
2406
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002407 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002408
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002409 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002410
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002411 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002412 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002413 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002414 goto failed;
2415 }
2416
Andre Guedes92c4c202012-06-07 19:05:44 -03002417 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002418 if (!uuid) {
2419 err = -ENOMEM;
2420 goto failed;
2421 }
2422
2423 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002424 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002425 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002426
Johan Hedbergde66aa62013-01-27 00:31:27 +02002427 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002428
Johan Hedberg890ea892013-03-15 17:06:52 -05002429 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002430
Johan Hedberg890ea892013-03-15 17:06:52 -05002431 update_class(&req);
2432 update_eir(&req);
2433
Johan Hedberg92da6092013-03-15 17:06:55 -05002434 err = hci_req_run(&req, add_uuid_complete);
2435 if (err < 0) {
2436 if (err != -ENODATA)
2437 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002438
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002439 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002440 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002441 goto failed;
2442 }
2443
2444 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002445 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002446 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002447 goto failed;
2448 }
2449
2450 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002451
2452failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002453 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002454 return err;
2455}
2456
Johan Hedberg24b78d02012-02-23 23:24:30 +02002457static bool enable_service_cache(struct hci_dev *hdev)
2458{
2459 if (!hdev_is_powered(hdev))
2460 return false;
2461
2462 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002463 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2464 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002465 return true;
2466 }
2467
2468 return false;
2469}
2470
Marcel Holtmann1904a852015-01-11 13:50:44 -08002471static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002472{
2473 BT_DBG("status 0x%02x", status);
2474
2475 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2476}
2477
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002478static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002479 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002481 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002482 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002483 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002484 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 -05002485 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002486 int err, found;
2487
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002488 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002489
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002490 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002491
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002492 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002493 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002494 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002495 goto unlock;
2496 }
2497
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002498 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002499 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002500
Johan Hedberg24b78d02012-02-23 23:24:30 +02002501 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002502 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002503 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002504 goto unlock;
2505 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002506
Johan Hedberg9246a862012-02-23 21:33:16 +02002507 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002508 }
2509
2510 found = 0;
2511
Johan Hedberg056341c2013-01-27 00:31:30 +02002512 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002513 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2514 continue;
2515
2516 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002517 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002518 found++;
2519 }
2520
2521 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002522 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002523 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002524 goto unlock;
2525 }
2526
Johan Hedberg9246a862012-02-23 21:33:16 +02002527update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002528 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002529
Johan Hedberg890ea892013-03-15 17:06:52 -05002530 update_class(&req);
2531 update_eir(&req);
2532
Johan Hedberg92da6092013-03-15 17:06:55 -05002533 err = hci_req_run(&req, remove_uuid_complete);
2534 if (err < 0) {
2535 if (err != -ENODATA)
2536 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002537
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002538 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002539 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002540 goto unlock;
2541 }
2542
2543 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002544 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002545 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002546 goto unlock;
2547 }
2548
2549 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002550
2551unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002552 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002553 return err;
2554}
2555
Marcel Holtmann1904a852015-01-11 13:50:44 -08002556static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002557{
2558 BT_DBG("status 0x%02x", status);
2559
2560 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2561}
2562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002563static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002564 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002565{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002566 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002567 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002568 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002569 int err;
2570
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002571 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002572
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002573 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002574 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2575 MGMT_STATUS_NOT_SUPPORTED);
2576
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002577 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002578
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002579 if (pending_eir_or_class(hdev)) {
2580 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2581 MGMT_STATUS_BUSY);
2582 goto unlock;
2583 }
2584
2585 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2586 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2587 MGMT_STATUS_INVALID_PARAMS);
2588 goto unlock;
2589 }
2590
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002591 hdev->major_class = cp->major;
2592 hdev->minor_class = cp->minor;
2593
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002594 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002595 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002596 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002597 goto unlock;
2598 }
2599
Johan Hedberg890ea892013-03-15 17:06:52 -05002600 hci_req_init(&req, hdev);
2601
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002602 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002603 hci_dev_unlock(hdev);
2604 cancel_delayed_work_sync(&hdev->service_cache);
2605 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002606 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002607 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002608
Johan Hedberg890ea892013-03-15 17:06:52 -05002609 update_class(&req);
2610
Johan Hedberg92da6092013-03-15 17:06:55 -05002611 err = hci_req_run(&req, set_class_complete);
2612 if (err < 0) {
2613 if (err != -ENODATA)
2614 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002615
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002616 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002617 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002618 goto unlock;
2619 }
2620
2621 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002622 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002623 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002624 goto unlock;
2625 }
2626
2627 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002628
Johan Hedbergb5235a62012-02-21 14:32:24 +02002629unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002630 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002631 return err;
2632}
2633
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002634static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002635 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002636{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002637 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002638 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2639 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002640 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002641 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002642 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002643
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002644 BT_DBG("request for %s", hdev->name);
2645
2646 if (!lmp_bredr_capable(hdev))
2647 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2648 MGMT_STATUS_NOT_SUPPORTED);
2649
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002650 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002651 if (key_count > max_key_count) {
2652 BT_ERR("load_link_keys: too big key_count value %u",
2653 key_count);
2654 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2655 MGMT_STATUS_INVALID_PARAMS);
2656 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002657
Johan Hedberg86742e12011-11-07 23:13:38 +02002658 expected_len = sizeof(*cp) + key_count *
2659 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002660 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002661 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002662 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002663 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002664 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002665 }
2666
Johan Hedberg4ae14302013-01-20 14:27:13 +02002667 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2668 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2669 MGMT_STATUS_INVALID_PARAMS);
2670
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002671 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002672 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002673
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002674 for (i = 0; i < key_count; i++) {
2675 struct mgmt_link_key_info *key = &cp->keys[i];
2676
Marcel Holtmann8e991132014-01-10 02:07:25 -08002677 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002678 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2679 MGMT_STATUS_INVALID_PARAMS);
2680 }
2681
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002682 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002683
2684 hci_link_keys_clear(hdev);
2685
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002686 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002687 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2688 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002689 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002690 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2691 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002692
2693 if (changed)
2694 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002695
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002696 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002697 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002698
Johan Hedberg58e92932014-06-24 14:00:26 +03002699 /* Always ignore debug keys and require a new pairing if
2700 * the user wants to use them.
2701 */
2702 if (key->type == HCI_LK_DEBUG_COMBINATION)
2703 continue;
2704
Johan Hedberg7652ff62014-06-24 13:15:49 +03002705 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2706 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002707 }
2708
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002709 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002710
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002711 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002712
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002713 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002714}
2715
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002716static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002717 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002718{
2719 struct mgmt_ev_device_unpaired ev;
2720
2721 bacpy(&ev.addr.bdaddr, bdaddr);
2722 ev.addr.type = addr_type;
2723
2724 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002726}
2727
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002728static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002729 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002730{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002731 struct mgmt_cp_unpair_device *cp = data;
2732 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002733 struct hci_cp_disconnect dc;
2734 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002735 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002736 int err;
2737
Johan Hedberga8a1d192011-11-10 15:54:38 +02002738 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002739 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2740 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002741
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002742 if (!bdaddr_type_is_valid(cp->addr.type))
2743 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2744 MGMT_STATUS_INVALID_PARAMS,
2745 &rp, sizeof(rp));
2746
Johan Hedberg118da702013-01-20 14:27:20 +02002747 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2748 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2749 MGMT_STATUS_INVALID_PARAMS,
2750 &rp, sizeof(rp));
2751
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002752 hci_dev_lock(hdev);
2753
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002754 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002757 goto unlock;
2758 }
2759
Johan Hedberge0b2b272014-02-18 17:14:31 +02002760 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002761 /* If disconnection is requested, then look up the
2762 * connection. If the remote device is connected, it
2763 * will be later used to terminate the link.
2764 *
2765 * Setting it to NULL explicitly will cause no
2766 * termination of the link.
2767 */
2768 if (cp->disconnect)
2769 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2770 &cp->addr.bdaddr);
2771 else
2772 conn = NULL;
2773
Johan Hedberg124f6e32012-02-09 13:50:12 +02002774 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002775 } else {
2776 u8 addr_type;
2777
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002778 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2779 &cp->addr.bdaddr);
2780 if (conn) {
2781 /* Defer clearing up the connection parameters
2782 * until closing to give a chance of keeping
2783 * them if a repairing happens.
2784 */
2785 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2786
2787 /* If disconnection is not requested, then
2788 * clear the connection variable so that the
2789 * link is not terminated.
2790 */
2791 if (!cp->disconnect)
2792 conn = NULL;
2793 }
2794
Johan Hedberge0b2b272014-02-18 17:14:31 +02002795 if (cp->addr.type == BDADDR_LE_PUBLIC)
2796 addr_type = ADDR_LE_DEV_PUBLIC;
2797 else
2798 addr_type = ADDR_LE_DEV_RANDOM;
2799
Johan Hedberga7ec7332014-02-18 17:14:35 +02002800 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2801
Johan Hedberge0b2b272014-02-18 17:14:31 +02002802 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2803 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002804
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002805 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002806 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002807 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002808 goto unlock;
2809 }
2810
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002811 /* If the connection variable is set, then termination of the
2812 * link is requested.
2813 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002814 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002815 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002816 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002817 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002818 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002819 }
2820
Johan Hedberg124f6e32012-02-09 13:50:12 +02002821 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002822 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002823 if (!cmd) {
2824 err = -ENOMEM;
2825 goto unlock;
2826 }
2827
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002828 cmd->cmd_complete = addr_cmd_complete;
2829
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002830 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002831 dc.reason = 0x13; /* Remote User Terminated Connection */
2832 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2833 if (err < 0)
2834 mgmt_pending_remove(cmd);
2835
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002836unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002837 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002838 return err;
2839}
2840
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002841static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002842 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002843{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002844 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002845 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002846 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002847 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002848 int err;
2849
2850 BT_DBG("");
2851
Johan Hedberg06a63b12013-01-20 14:27:21 +02002852 memset(&rp, 0, sizeof(rp));
2853 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2854 rp.addr.type = cp->addr.type;
2855
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002856 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002857 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2858 MGMT_STATUS_INVALID_PARAMS,
2859 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002860
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002861 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002862
2863 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002864 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2865 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002866 goto failed;
2867 }
2868
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002869 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002870 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2871 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002872 goto failed;
2873 }
2874
Andre Guedes591f47f2012-04-24 21:02:49 -03002875 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002876 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2877 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002878 else
2879 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002880
Vishal Agarwalf9607272012-06-13 05:32:43 +05302881 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002882 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2883 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002884 goto failed;
2885 }
2886
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002887 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002888 if (!cmd) {
2889 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002890 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002891 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002892
Johan Hedbergf5818c22014-12-05 13:36:02 +02002893 cmd->cmd_complete = generic_cmd_complete;
2894
Johan Hedberge3f2f922014-08-18 20:33:33 +03002895 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002896 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002897 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002898
2899failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002900 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002901 return err;
2902}
2903
Andre Guedes57c14772012-04-24 21:02:50 -03002904static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002905{
2906 switch (link_type) {
2907 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002908 switch (addr_type) {
2909 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002910 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002911
Johan Hedberg48264f02011-11-09 13:58:58 +02002912 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002913 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002914 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002915 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002916
Johan Hedberg4c659c32011-11-07 23:13:39 +02002917 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002918 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002919 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002920 }
2921}
2922
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002923static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2924 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002925{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002926 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002927 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002928 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002929 int err;
2930 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002931
2932 BT_DBG("");
2933
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002934 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002935
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002936 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002937 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002938 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002939 goto unlock;
2940 }
2941
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002942 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002943 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2944 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002945 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002946 }
2947
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002948 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002949 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002950 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002951 err = -ENOMEM;
2952 goto unlock;
2953 }
2954
Johan Hedberg2784eb42011-01-21 13:56:35 +02002955 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002956 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002957 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2958 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002959 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002960 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002961 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002962 continue;
2963 i++;
2964 }
2965
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002966 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002967
Johan Hedberg4c659c32011-11-07 23:13:39 +02002968 /* Recalculate length in case of filtered SCO connections, etc */
2969 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002970
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002971 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002972 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002973
Johan Hedberga38528f2011-01-22 06:46:43 +02002974 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002975
2976unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002977 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002978 return err;
2979}
2980
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002981static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002983{
2984 struct pending_cmd *cmd;
2985 int err;
2986
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002987 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002988 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002989 if (!cmd)
2990 return -ENOMEM;
2991
Johan Hedbergd8457692012-02-17 14:24:57 +02002992 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002993 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002994 if (err < 0)
2995 mgmt_pending_remove(cmd);
2996
2997 return err;
2998}
2999
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003000static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003001 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003002{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003003 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003004 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003005 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003006 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003007 int err;
3008
3009 BT_DBG("");
3010
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003011 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003012
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003013 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003014 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003015 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003016 goto failed;
3017 }
3018
Johan Hedbergd8457692012-02-17 14:24:57 +02003019 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003020 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003021 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003022 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003023 goto failed;
3024 }
3025
3026 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003027 struct mgmt_cp_pin_code_neg_reply ncp;
3028
3029 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003030
3031 BT_ERR("PIN code is not 16 bytes long");
3032
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003033 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003034 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003035 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003036 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003037
3038 goto failed;
3039 }
3040
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003041 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003042 if (!cmd) {
3043 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003044 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003045 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003046
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003047 cmd->cmd_complete = addr_cmd_complete;
3048
Johan Hedbergd8457692012-02-17 14:24:57 +02003049 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003050 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003051 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003052
3053 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3054 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003055 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003056
3057failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003058 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003059 return err;
3060}
3061
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003062static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3063 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003064{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003065 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003066
3067 BT_DBG("");
3068
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003069 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3070 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3071 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3072
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003073 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003074
3075 hdev->io_capability = cp->io_capability;
3076
3077 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003078 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003079
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003080 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003081
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003082 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3083 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003084}
3085
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003086static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003087{
3088 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003089 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003090
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003091 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003092 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3093 continue;
3094
Johan Hedberge9a416b2011-02-19 12:05:56 -03003095 if (cmd->user_data != conn)
3096 continue;
3097
3098 return cmd;
3099 }
3100
3101 return NULL;
3102}
3103
Johan Hedberg9df74652014-12-19 22:26:03 +02003104static int pairing_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003105{
3106 struct mgmt_rp_pair_device rp;
3107 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003108 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003109
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003110 bacpy(&rp.addr.bdaddr, &conn->dst);
3111 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003112
Johan Hedberg9df74652014-12-19 22:26:03 +02003113 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
3114 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003115
3116 /* So we don't get further callbacks for this connection */
3117 conn->connect_cfm_cb = NULL;
3118 conn->security_cfm_cb = NULL;
3119 conn->disconn_cfm_cb = NULL;
3120
David Herrmann76a68ba2013-04-06 20:28:37 +02003121 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003122
3123 /* The device is paired so there is no need to remove
3124 * its connection parameters anymore.
3125 */
3126 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003127
3128 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003129
3130 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003131}
3132
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003133void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3134{
3135 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3136 struct pending_cmd *cmd;
3137
3138 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003139 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003140 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003141 mgmt_pending_remove(cmd);
3142 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003143}
3144
Johan Hedberge9a416b2011-02-19 12:05:56 -03003145static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3146{
3147 struct pending_cmd *cmd;
3148
3149 BT_DBG("status %u", status);
3150
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003151 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003152 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003153 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003154 return;
3155 }
3156
3157 cmd->cmd_complete(cmd, mgmt_status(status));
3158 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003159}
3160
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003161static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303162{
3163 struct pending_cmd *cmd;
3164
3165 BT_DBG("status %u", status);
3166
3167 if (!status)
3168 return;
3169
3170 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003171 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303172 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003173 return;
3174 }
3175
3176 cmd->cmd_complete(cmd, mgmt_status(status));
3177 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303178}
3179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003180static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003181 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003182{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003183 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003184 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003185 struct pending_cmd *cmd;
3186 u8 sec_level, auth_type;
3187 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003188 int err;
3189
3190 BT_DBG("");
3191
Szymon Jancf950a30e2013-01-18 12:48:07 +01003192 memset(&rp, 0, sizeof(rp));
3193 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3194 rp.addr.type = cp->addr.type;
3195
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003196 if (!bdaddr_type_is_valid(cp->addr.type))
3197 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3198 MGMT_STATUS_INVALID_PARAMS,
3199 &rp, sizeof(rp));
3200
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003201 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3202 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3203 MGMT_STATUS_INVALID_PARAMS,
3204 &rp, sizeof(rp));
3205
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003206 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003207
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003208 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003209 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3210 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003211 goto unlock;
3212 }
3213
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003214 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003215 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003216
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003217 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003218 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3219 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003220 } else {
3221 u8 addr_type;
3222
3223 /* Convert from L2CAP channel address type to HCI address type
3224 */
3225 if (cp->addr.type == BDADDR_LE_PUBLIC)
3226 addr_type = ADDR_LE_DEV_PUBLIC;
3227 else
3228 addr_type = ADDR_LE_DEV_RANDOM;
3229
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003230 /* When pairing a new device, it is expected to remember
3231 * this device for future connections. Adding the connection
3232 * parameter information ahead of time allows tracking
3233 * of the slave preferred values and will speed up any
3234 * further connection establishment.
3235 *
3236 * If connection parameters already exist, then they
3237 * will be kept and this function does nothing.
3238 */
3239 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3240
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003241 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003242 sec_level, HCI_LE_CONN_TIMEOUT,
3243 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003244 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003245
Ville Tervo30e76272011-02-22 16:10:53 -03003246 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003247 int status;
3248
3249 if (PTR_ERR(conn) == -EBUSY)
3250 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003251 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3252 status = MGMT_STATUS_NOT_SUPPORTED;
3253 else if (PTR_ERR(conn) == -ECONNREFUSED)
3254 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003255 else
3256 status = MGMT_STATUS_CONNECT_FAILED;
3257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003258 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003259 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003260 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003261 goto unlock;
3262 }
3263
3264 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003265 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003266 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003267 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003268 goto unlock;
3269 }
3270
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003271 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003272 if (!cmd) {
3273 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003274 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003275 goto unlock;
3276 }
3277
Johan Hedberg04ab2742014-12-05 13:36:04 +02003278 cmd->cmd_complete = pairing_complete;
3279
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003280 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003281 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003282 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003283 conn->security_cfm_cb = pairing_complete_cb;
3284 conn->disconn_cfm_cb = pairing_complete_cb;
3285 } else {
3286 conn->connect_cfm_cb = le_pairing_complete_cb;
3287 conn->security_cfm_cb = le_pairing_complete_cb;
3288 conn->disconn_cfm_cb = le_pairing_complete_cb;
3289 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003290
Johan Hedberge9a416b2011-02-19 12:05:56 -03003291 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003292 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003293
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003294 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003295 hci_conn_security(conn, sec_level, auth_type, true)) {
3296 cmd->cmd_complete(cmd, 0);
3297 mgmt_pending_remove(cmd);
3298 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003299
3300 err = 0;
3301
3302unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003303 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003304 return err;
3305}
3306
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003307static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3308 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003309{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003310 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003311 struct pending_cmd *cmd;
3312 struct hci_conn *conn;
3313 int err;
3314
3315 BT_DBG("");
3316
Johan Hedberg28424702012-02-02 04:02:29 +02003317 hci_dev_lock(hdev);
3318
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003319 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003320 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003321 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003322 goto unlock;
3323 }
3324
Johan Hedberg28424702012-02-02 04:02:29 +02003325 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3326 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003327 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003328 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003329 goto unlock;
3330 }
3331
3332 conn = cmd->user_data;
3333
3334 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003335 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003336 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003337 goto unlock;
3338 }
3339
Johan Hedberga511b352014-12-11 21:45:45 +02003340 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3341 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003342
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003343 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003344 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003345unlock:
3346 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003347 return err;
3348}
3349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003350static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003351 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003352 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003353{
Johan Hedberga5c29682011-02-19 12:05:57 -03003354 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003355 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003356 int err;
3357
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003358 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003359
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003360 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003361 err = cmd_complete(sk, hdev->id, mgmt_op,
3362 MGMT_STATUS_NOT_POWERED, addr,
3363 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003364 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003365 }
3366
Johan Hedberg1707c602013-03-15 17:07:15 -05003367 if (addr->type == BDADDR_BREDR)
3368 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003369 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003370 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003371
Johan Hedberg272d90d2012-02-09 15:26:12 +02003372 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003373 err = cmd_complete(sk, hdev->id, mgmt_op,
3374 MGMT_STATUS_NOT_CONNECTED, addr,
3375 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003376 goto done;
3377 }
3378
Johan Hedberg1707c602013-03-15 17:07:15 -05003379 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003380 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003381 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003382 err = cmd_complete(sk, hdev->id, mgmt_op,
3383 MGMT_STATUS_SUCCESS, addr,
3384 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003385 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003386 err = cmd_complete(sk, hdev->id, mgmt_op,
3387 MGMT_STATUS_FAILED, addr,
3388 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003389
Brian Gix47c15e22011-11-16 13:53:14 -08003390 goto done;
3391 }
3392
Johan Hedberg1707c602013-03-15 17:07:15 -05003393 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003394 if (!cmd) {
3395 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003396 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003397 }
3398
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003399 cmd->cmd_complete = addr_cmd_complete;
3400
Brian Gix0df4c182011-11-16 13:53:13 -08003401 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003402 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3403 struct hci_cp_user_passkey_reply cp;
3404
Johan Hedberg1707c602013-03-15 17:07:15 -05003405 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003406 cp.passkey = passkey;
3407 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3408 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003409 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3410 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003411
Johan Hedberga664b5b2011-02-19 12:06:02 -03003412 if (err < 0)
3413 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003414
Brian Gix0df4c182011-11-16 13:53:13 -08003415done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003416 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003417 return err;
3418}
3419
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303420static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3421 void *data, u16 len)
3422{
3423 struct mgmt_cp_pin_code_neg_reply *cp = data;
3424
3425 BT_DBG("");
3426
Johan Hedberg1707c602013-03-15 17:07:15 -05003427 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303428 MGMT_OP_PIN_CODE_NEG_REPLY,
3429 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3430}
3431
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003432static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3433 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003434{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003435 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003436
3437 BT_DBG("");
3438
3439 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003440 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003441 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003442
Johan Hedberg1707c602013-03-15 17:07:15 -05003443 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003444 MGMT_OP_USER_CONFIRM_REPLY,
3445 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003446}
3447
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003448static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003449 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003450{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003451 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003452
3453 BT_DBG("");
3454
Johan Hedberg1707c602013-03-15 17:07:15 -05003455 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003456 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3457 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003458}
3459
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003460static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3461 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003462{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003463 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003464
3465 BT_DBG("");
3466
Johan Hedberg1707c602013-03-15 17:07:15 -05003467 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003468 MGMT_OP_USER_PASSKEY_REPLY,
3469 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003470}
3471
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003472static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003473 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003474{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003475 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003476
3477 BT_DBG("");
3478
Johan Hedberg1707c602013-03-15 17:07:15 -05003479 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003480 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3481 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003482}
3483
Johan Hedberg13928972013-03-15 17:07:00 -05003484static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003485{
Johan Hedberg13928972013-03-15 17:07:00 -05003486 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003487 struct hci_cp_write_local_name cp;
3488
Johan Hedberg13928972013-03-15 17:07:00 -05003489 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003490
Johan Hedberg890ea892013-03-15 17:06:52 -05003491 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003492}
3493
Marcel Holtmann1904a852015-01-11 13:50:44 -08003494static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003495{
3496 struct mgmt_cp_set_local_name *cp;
3497 struct pending_cmd *cmd;
3498
3499 BT_DBG("status 0x%02x", status);
3500
3501 hci_dev_lock(hdev);
3502
3503 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3504 if (!cmd)
3505 goto unlock;
3506
3507 cp = cmd->param;
3508
3509 if (status)
3510 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3511 mgmt_status(status));
3512 else
3513 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3514 cp, sizeof(*cp));
3515
3516 mgmt_pending_remove(cmd);
3517
3518unlock:
3519 hci_dev_unlock(hdev);
3520}
3521
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003522static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003523 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003524{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003525 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003526 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003527 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003528 int err;
3529
3530 BT_DBG("");
3531
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003532 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003533
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003534 /* If the old values are the same as the new ones just return a
3535 * direct command complete event.
3536 */
3537 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3538 !memcmp(hdev->short_name, cp->short_name,
3539 sizeof(hdev->short_name))) {
3540 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3541 data, len);
3542 goto failed;
3543 }
3544
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003545 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003546
Johan Hedbergb5235a62012-02-21 14:32:24 +02003547 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003548 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003549
3550 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003551 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003552 if (err < 0)
3553 goto failed;
3554
3555 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003556 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003557
Johan Hedbergb5235a62012-02-21 14:32:24 +02003558 goto failed;
3559 }
3560
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003561 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003562 if (!cmd) {
3563 err = -ENOMEM;
3564 goto failed;
3565 }
3566
Johan Hedberg13928972013-03-15 17:07:00 -05003567 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3568
Johan Hedberg890ea892013-03-15 17:06:52 -05003569 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003570
3571 if (lmp_bredr_capable(hdev)) {
3572 update_name(&req);
3573 update_eir(&req);
3574 }
3575
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003576 /* The name is stored in the scan response data and so
3577 * no need to udpate the advertising data here.
3578 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003579 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003580 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003581
Johan Hedberg13928972013-03-15 17:07:00 -05003582 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003583 if (err < 0)
3584 mgmt_pending_remove(cmd);
3585
3586failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003587 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003588 return err;
3589}
3590
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003591static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003592 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003593{
Szymon Jancc35938b2011-03-22 13:12:21 +01003594 struct pending_cmd *cmd;
3595 int err;
3596
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003597 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003598
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003599 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003600
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003601 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003602 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003603 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003604 goto unlock;
3605 }
3606
Andre Guedes9a1a1992012-07-24 15:03:48 -03003607 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003608 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003609 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003610 goto unlock;
3611 }
3612
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003613 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003614 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003615 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003616 goto unlock;
3617 }
3618
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003619 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003620 if (!cmd) {
3621 err = -ENOMEM;
3622 goto unlock;
3623 }
3624
Johan Hedberg710f11c2014-05-26 11:21:22 +03003625 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003626 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3627 0, NULL);
3628 else
3629 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3630
Szymon Jancc35938b2011-03-22 13:12:21 +01003631 if (err < 0)
3632 mgmt_pending_remove(cmd);
3633
3634unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003635 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003636 return err;
3637}
3638
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003639static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003640 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003641{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003642 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003643 int err;
3644
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003645 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003646
Johan Hedberg5d57e792015-01-23 10:10:38 +02003647 if (!bdaddr_type_is_valid(addr->type))
3648 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3649 MGMT_STATUS_INVALID_PARAMS, addr,
3650 sizeof(*addr));
3651
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003652 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003653
Marcel Holtmannec109112014-01-10 02:07:30 -08003654 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3655 struct mgmt_cp_add_remote_oob_data *cp = data;
3656 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003657
Johan Hedbergc19a4952014-11-17 20:52:19 +02003658 if (cp->addr.type != BDADDR_BREDR) {
3659 err = cmd_complete(sk, hdev->id,
3660 MGMT_OP_ADD_REMOTE_OOB_DATA,
3661 MGMT_STATUS_INVALID_PARAMS,
3662 &cp->addr, sizeof(cp->addr));
3663 goto unlock;
3664 }
3665
Marcel Holtmannec109112014-01-10 02:07:30 -08003666 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003667 cp->addr.type, cp->hash,
3668 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003669 if (err < 0)
3670 status = MGMT_STATUS_FAILED;
3671 else
3672 status = MGMT_STATUS_SUCCESS;
3673
3674 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3675 status, &cp->addr, sizeof(cp->addr));
3676 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3677 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003678 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003679 u8 status;
3680
Johan Hedberg86df9202014-10-26 20:52:27 +01003681 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003682 /* Enforce zero-valued 192-bit parameters as
3683 * long as legacy SMP OOB isn't implemented.
3684 */
3685 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3686 memcmp(cp->hash192, ZERO_KEY, 16)) {
3687 err = cmd_complete(sk, hdev->id,
3688 MGMT_OP_ADD_REMOTE_OOB_DATA,
3689 MGMT_STATUS_INVALID_PARAMS,
3690 addr, sizeof(*addr));
3691 goto unlock;
3692 }
3693
Johan Hedberg86df9202014-10-26 20:52:27 +01003694 rand192 = NULL;
3695 hash192 = NULL;
3696 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003697 /* In case one of the P-192 values is set to zero,
3698 * then just disable OOB data for P-192.
3699 */
3700 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3701 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3702 rand192 = NULL;
3703 hash192 = NULL;
3704 } else {
3705 rand192 = cp->rand192;
3706 hash192 = cp->hash192;
3707 }
3708 }
3709
3710 /* In case one of the P-256 values is set to zero, then just
3711 * disable OOB data for P-256.
3712 */
3713 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3714 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3715 rand256 = NULL;
3716 hash256 = NULL;
3717 } else {
3718 rand256 = cp->rand256;
3719 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003720 }
3721
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003722 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003723 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003724 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003725 if (err < 0)
3726 status = MGMT_STATUS_FAILED;
3727 else
3728 status = MGMT_STATUS_SUCCESS;
3729
3730 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3731 status, &cp->addr, sizeof(cp->addr));
3732 } else {
3733 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3734 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3735 MGMT_STATUS_INVALID_PARAMS);
3736 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003737
Johan Hedbergc19a4952014-11-17 20:52:19 +02003738unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003739 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003740 return err;
3741}
3742
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003743static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003744 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003745{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003746 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003747 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003748 int err;
3749
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003750 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003751
Johan Hedbergc19a4952014-11-17 20:52:19 +02003752 if (cp->addr.type != BDADDR_BREDR)
3753 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3754 MGMT_STATUS_INVALID_PARAMS,
3755 &cp->addr, sizeof(cp->addr));
3756
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003757 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003758
Johan Hedbergeedbd582014-11-15 09:34:23 +02003759 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3760 hci_remote_oob_data_clear(hdev);
3761 status = MGMT_STATUS_SUCCESS;
3762 goto done;
3763 }
3764
Johan Hedberg6928a922014-10-26 20:46:09 +01003765 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003766 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003767 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003768 else
Szymon Janca6785be2012-12-13 15:11:21 +01003769 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003770
Johan Hedbergeedbd582014-11-15 09:34:23 +02003771done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003772 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003773 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003774
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003775 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003776 return err;
3777}
3778
Marcel Holtmann80190442014-12-04 11:36:36 +01003779static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003780{
Marcel Holtmann80190442014-12-04 11:36:36 +01003781 struct hci_dev *hdev = req->hdev;
3782 struct hci_cp_le_set_scan_param param_cp;
3783 struct hci_cp_le_set_scan_enable enable_cp;
3784 struct hci_cp_inquiry inq_cp;
3785 /* General inquiry access code (GIAC) */
3786 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3787 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003788 int err;
3789
Marcel Holtmann80190442014-12-04 11:36:36 +01003790 switch (hdev->discovery.type) {
3791 case DISCOV_TYPE_BREDR:
3792 *status = mgmt_bredr_support(hdev);
3793 if (*status)
3794 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003795
Marcel Holtmann80190442014-12-04 11:36:36 +01003796 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3797 *status = MGMT_STATUS_BUSY;
3798 return false;
3799 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003800
Marcel Holtmann80190442014-12-04 11:36:36 +01003801 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003802
Marcel Holtmann80190442014-12-04 11:36:36 +01003803 memset(&inq_cp, 0, sizeof(inq_cp));
3804 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3805 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3806 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3807 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003808
Marcel Holtmann80190442014-12-04 11:36:36 +01003809 case DISCOV_TYPE_LE:
3810 case DISCOV_TYPE_INTERLEAVED:
3811 *status = mgmt_le_support(hdev);
3812 if (*status)
3813 return false;
3814
3815 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3816 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3817 *status = MGMT_STATUS_NOT_SUPPORTED;
3818 return false;
3819 }
3820
3821 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3822 /* Don't let discovery abort an outgoing
3823 * connection attempt that's using directed
3824 * advertising.
3825 */
3826 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3827 BT_CONNECT)) {
3828 *status = MGMT_STATUS_REJECTED;
3829 return false;
3830 }
3831
3832 disable_advertising(req);
3833 }
3834
3835 /* If controller is scanning, it means the background scanning
3836 * is running. Thus, we should temporarily stop it in order to
3837 * set the discovery scanning parameters.
3838 */
3839 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3840 hci_req_add_le_scan_disable(req);
3841
3842 memset(&param_cp, 0, sizeof(param_cp));
3843
3844 /* All active scans will be done with either a resolvable
3845 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003846 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003847 */
3848 err = hci_update_random_address(req, true, &own_addr_type);
3849 if (err < 0) {
3850 *status = MGMT_STATUS_FAILED;
3851 return false;
3852 }
3853
3854 param_cp.type = LE_SCAN_ACTIVE;
3855 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3856 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3857 param_cp.own_address_type = own_addr_type;
3858 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3859 &param_cp);
3860
3861 memset(&enable_cp, 0, sizeof(enable_cp));
3862 enable_cp.enable = LE_SCAN_ENABLE;
3863 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3864 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3865 &enable_cp);
3866 break;
3867
3868 default:
3869 *status = MGMT_STATUS_INVALID_PARAMS;
3870 return false;
3871 }
3872
3873 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003874}
3875
Marcel Holtmann1904a852015-01-11 13:50:44 -08003876static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3877 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003878{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003879 struct pending_cmd *cmd;
3880 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003881
Andre Guedes7c307722013-04-30 15:29:28 -03003882 BT_DBG("status %d", status);
3883
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003884 hci_dev_lock(hdev);
3885
3886 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003887 if (!cmd)
3888 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3889
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003890 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003891 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003892 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003893 }
3894
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003895 if (status) {
3896 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3897 goto unlock;
3898 }
3899
Andre Guedes7c307722013-04-30 15:29:28 -03003900 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003901
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003902 /* If the scan involves LE scan, pick proper timeout to schedule
3903 * hdev->le_scan_disable that will stop it.
3904 */
Andre Guedes7c307722013-04-30 15:29:28 -03003905 switch (hdev->discovery.type) {
3906 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003907 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003908 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003909 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003910 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003911 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003912 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003913 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003914 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003915 default:
3916 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003917 timeout = 0;
3918 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003919 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003920
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003921 if (timeout) {
3922 /* When service discovery is used and the controller has
3923 * a strict duplicate filter, it is important to remember
3924 * the start and duration of the scan. This is required
3925 * for restarting scanning during the discovery phase.
3926 */
3927 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3928 &hdev->quirks) &&
3929 (hdev->discovery.uuid_count > 0 ||
3930 hdev->discovery.rssi != HCI_RSSI_INVALID)) {
3931 hdev->discovery.scan_start = jiffies;
3932 hdev->discovery.scan_duration = timeout;
3933 }
3934
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003935 queue_delayed_work(hdev->workqueue,
3936 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003937 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003938
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003939unlock:
3940 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003941}
3942
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003943static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003944 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003945{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003946 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003947 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003948 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003949 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003950 int err;
3951
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003952 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003953
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003954 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003955
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003956 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003957 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3958 MGMT_STATUS_NOT_POWERED,
3959 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003960 goto failed;
3961 }
3962
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003963 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3964 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003965 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3966 MGMT_STATUS_BUSY, &cp->type,
3967 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003968 goto failed;
3969 }
3970
Johan Hedberg2922a942014-12-05 13:36:06 +02003971 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003972 if (!cmd) {
3973 err = -ENOMEM;
3974 goto failed;
3975 }
3976
Johan Hedberg2922a942014-12-05 13:36:06 +02003977 cmd->cmd_complete = generic_cmd_complete;
3978
Marcel Holtmann22078802014-12-05 11:45:22 +01003979 /* Clear the discovery filter first to free any previously
3980 * allocated memory for the UUID list.
3981 */
3982 hci_discovery_filter_clear(hdev);
3983
Andre Guedes4aab14e2012-02-17 20:39:36 -03003984 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01003985 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03003986
Andre Guedes7c307722013-04-30 15:29:28 -03003987 hci_req_init(&req, hdev);
3988
Marcel Holtmann80190442014-12-04 11:36:36 +01003989 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003990 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003991 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003992 mgmt_pending_remove(cmd);
3993 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003994 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003995
Andre Guedes7c307722013-04-30 15:29:28 -03003996 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003997 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003998 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003999 goto failed;
4000 }
4001
4002 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004003
4004failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004005 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004006 return err;
4007}
4008
Johan Hedberg9df74652014-12-19 22:26:03 +02004009static int service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004010{
Johan Hedberg9df74652014-12-19 22:26:03 +02004011 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4012 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004013}
4014
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004015static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4016 void *data, u16 len)
4017{
4018 struct mgmt_cp_start_service_discovery *cp = data;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004019 struct pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004020 struct hci_request req;
4021 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4022 u16 uuid_count, expected_len;
4023 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004024 int err;
4025
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004026 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004027
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004028 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004029
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004030 if (!hdev_is_powered(hdev)) {
4031 err = cmd_complete(sk, hdev->id,
4032 MGMT_OP_START_SERVICE_DISCOVERY,
4033 MGMT_STATUS_NOT_POWERED,
4034 &cp->type, sizeof(cp->type));
4035 goto failed;
4036 }
4037
4038 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4039 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
4040 err = cmd_complete(sk, hdev->id,
4041 MGMT_OP_START_SERVICE_DISCOVERY,
4042 MGMT_STATUS_BUSY, &cp->type,
4043 sizeof(cp->type));
4044 goto failed;
4045 }
4046
4047 uuid_count = __le16_to_cpu(cp->uuid_count);
4048 if (uuid_count > max_uuid_count) {
4049 BT_ERR("service_discovery: too big uuid_count value %u",
4050 uuid_count);
4051 err = cmd_complete(sk, hdev->id,
4052 MGMT_OP_START_SERVICE_DISCOVERY,
4053 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4054 sizeof(cp->type));
4055 goto failed;
4056 }
4057
4058 expected_len = sizeof(*cp) + uuid_count * 16;
4059 if (expected_len != len) {
4060 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4061 expected_len, len);
4062 err = cmd_complete(sk, hdev->id,
4063 MGMT_OP_START_SERVICE_DISCOVERY,
4064 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4065 sizeof(cp->type));
4066 goto failed;
4067 }
4068
4069 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004070 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004071 if (!cmd) {
4072 err = -ENOMEM;
4073 goto failed;
4074 }
4075
Johan Hedberg2922a942014-12-05 13:36:06 +02004076 cmd->cmd_complete = service_discovery_cmd_complete;
4077
Marcel Holtmann22078802014-12-05 11:45:22 +01004078 /* Clear the discovery filter first to free any previously
4079 * allocated memory for the UUID list.
4080 */
4081 hci_discovery_filter_clear(hdev);
4082
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004083 hdev->discovery.type = cp->type;
4084 hdev->discovery.rssi = cp->rssi;
4085 hdev->discovery.uuid_count = uuid_count;
4086
4087 if (uuid_count > 0) {
4088 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4089 GFP_KERNEL);
4090 if (!hdev->discovery.uuids) {
4091 err = cmd_complete(sk, hdev->id,
4092 MGMT_OP_START_SERVICE_DISCOVERY,
4093 MGMT_STATUS_FAILED,
4094 &cp->type, sizeof(cp->type));
4095 mgmt_pending_remove(cmd);
4096 goto failed;
4097 }
4098 }
4099
4100 hci_req_init(&req, hdev);
4101
4102 if (!trigger_discovery(&req, &status)) {
4103 err = cmd_complete(sk, hdev->id,
4104 MGMT_OP_START_SERVICE_DISCOVERY,
4105 status, &cp->type, sizeof(cp->type));
4106 mgmt_pending_remove(cmd);
4107 goto failed;
4108 }
4109
4110 err = hci_req_run(&req, start_discovery_complete);
4111 if (err < 0) {
4112 mgmt_pending_remove(cmd);
4113 goto failed;
4114 }
4115
4116 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4117
4118failed:
4119 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004120 return err;
4121}
4122
Marcel Holtmann1904a852015-01-11 13:50:44 -08004123static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004124{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004125 struct pending_cmd *cmd;
4126
Andre Guedes0e05bba2013-04-30 15:29:33 -03004127 BT_DBG("status %d", status);
4128
4129 hci_dev_lock(hdev);
4130
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004131 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4132 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004133 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004134 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004135 }
4136
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004137 if (!status)
4138 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004139
Andre Guedes0e05bba2013-04-30 15:29:33 -03004140 hci_dev_unlock(hdev);
4141}
4142
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004143static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004144 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004145{
Johan Hedbergd9306502012-02-20 23:25:18 +02004146 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004147 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004148 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004149 int err;
4150
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004151 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004152
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004153 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004154
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004155 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004156 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004157 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4158 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004159 goto unlock;
4160 }
4161
4162 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004163 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004164 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4165 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004166 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004167 }
4168
Johan Hedberg2922a942014-12-05 13:36:06 +02004169 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004170 if (!cmd) {
4171 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004172 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004173 }
4174
Johan Hedberg2922a942014-12-05 13:36:06 +02004175 cmd->cmd_complete = generic_cmd_complete;
4176
Andre Guedes0e05bba2013-04-30 15:29:33 -03004177 hci_req_init(&req, hdev);
4178
Johan Hedberg21a60d32014-06-10 14:05:58 +03004179 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004180
Johan Hedberg21a60d32014-06-10 14:05:58 +03004181 err = hci_req_run(&req, stop_discovery_complete);
4182 if (!err) {
4183 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004184 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004185 }
4186
Johan Hedberg21a60d32014-06-10 14:05:58 +03004187 mgmt_pending_remove(cmd);
4188
4189 /* If no HCI commands were sent we're done */
4190 if (err == -ENODATA) {
4191 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4192 &mgmt_cp->type, sizeof(mgmt_cp->type));
4193 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4194 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004195
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004196unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004197 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004198 return err;
4199}
4200
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004201static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004202 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004203{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004204 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004205 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004206 int err;
4207
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004208 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004209
Johan Hedberg561aafb2012-01-04 13:31:59 +02004210 hci_dev_lock(hdev);
4211
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004212 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004213 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4214 MGMT_STATUS_FAILED, &cp->addr,
4215 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004216 goto failed;
4217 }
4218
Johan Hedberga198e7b2012-02-17 14:27:06 +02004219 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004220 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004221 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4222 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4223 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004224 goto failed;
4225 }
4226
4227 if (cp->name_known) {
4228 e->name_state = NAME_KNOWN;
4229 list_del(&e->list);
4230 } else {
4231 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004232 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004233 }
4234
Johan Hedberge3846622013-01-09 15:29:33 +02004235 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4236 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004237
4238failed:
4239 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004240 return err;
4241}
4242
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004243static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004244 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004245{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004246 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004247 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004248 int err;
4249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004250 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004251
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004252 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004253 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4254 MGMT_STATUS_INVALID_PARAMS,
4255 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004256
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004257 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004258
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004259 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4260 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004261 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004262 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004263 goto done;
4264 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004265
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004266 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4267 sk);
4268 status = MGMT_STATUS_SUCCESS;
4269
4270done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004271 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004272 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004273
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004274 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004275
4276 return err;
4277}
4278
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004279static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004280 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004281{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004282 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004283 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004284 int err;
4285
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004286 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004287
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004288 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004289 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4290 MGMT_STATUS_INVALID_PARAMS,
4291 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004292
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004293 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004294
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004295 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4296 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004297 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004298 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004299 goto done;
4300 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004301
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004302 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4303 sk);
4304 status = MGMT_STATUS_SUCCESS;
4305
4306done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004307 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004308 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004309
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004310 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004311
4312 return err;
4313}
4314
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004315static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4316 u16 len)
4317{
4318 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004319 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004320 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004321 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004322
4323 BT_DBG("%s", hdev->name);
4324
Szymon Jancc72d4b82012-03-16 16:02:57 +01004325 source = __le16_to_cpu(cp->source);
4326
4327 if (source > 0x0002)
4328 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4329 MGMT_STATUS_INVALID_PARAMS);
4330
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004331 hci_dev_lock(hdev);
4332
Szymon Jancc72d4b82012-03-16 16:02:57 +01004333 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004334 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4335 hdev->devid_product = __le16_to_cpu(cp->product);
4336 hdev->devid_version = __le16_to_cpu(cp->version);
4337
4338 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4339
Johan Hedberg890ea892013-03-15 17:06:52 -05004340 hci_req_init(&req, hdev);
4341 update_eir(&req);
4342 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004343
4344 hci_dev_unlock(hdev);
4345
4346 return err;
4347}
4348
Marcel Holtmann1904a852015-01-11 13:50:44 -08004349static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4350 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004351{
4352 struct cmd_lookup match = { NULL, hdev };
4353
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304354 hci_dev_lock(hdev);
4355
Johan Hedberg4375f102013-09-25 13:26:10 +03004356 if (status) {
4357 u8 mgmt_err = mgmt_status(status);
4358
4359 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4360 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304361 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004362 }
4363
Johan Hedbergc93bd152014-07-08 15:07:48 +03004364 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4365 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4366 else
4367 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4368
Johan Hedberg4375f102013-09-25 13:26:10 +03004369 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4370 &match);
4371
4372 new_settings(hdev, match.sk);
4373
4374 if (match.sk)
4375 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304376
4377unlock:
4378 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004379}
4380
Marcel Holtmann21b51872013-10-10 09:47:53 -07004381static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4382 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004383{
4384 struct mgmt_mode *cp = data;
4385 struct pending_cmd *cmd;
4386 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004387 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004388 int err;
4389
4390 BT_DBG("request for %s", hdev->name);
4391
Johan Hedberge6fe7982013-10-02 15:45:22 +03004392 status = mgmt_le_support(hdev);
4393 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004394 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004395 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004396
4397 if (cp->val != 0x00 && cp->val != 0x01)
4398 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4399 MGMT_STATUS_INVALID_PARAMS);
4400
4401 hci_dev_lock(hdev);
4402
4403 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004404 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004405
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004406 /* The following conditions are ones which mean that we should
4407 * not do any HCI communication but directly send a mgmt
4408 * response to user space (after toggling the flag if
4409 * necessary).
4410 */
4411 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004412 hci_conn_num(hdev, LE_LINK) > 0 ||
4413 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4414 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004415 bool changed = false;
4416
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004417 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4418 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004419 changed = true;
4420 }
4421
4422 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4423 if (err < 0)
4424 goto unlock;
4425
4426 if (changed)
4427 err = new_settings(hdev, sk);
4428
4429 goto unlock;
4430 }
4431
4432 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4433 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4434 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4435 MGMT_STATUS_BUSY);
4436 goto unlock;
4437 }
4438
4439 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4440 if (!cmd) {
4441 err = -ENOMEM;
4442 goto unlock;
4443 }
4444
4445 hci_req_init(&req, hdev);
4446
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004447 if (val)
4448 enable_advertising(&req);
4449 else
4450 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004451
4452 err = hci_req_run(&req, set_advertising_complete);
4453 if (err < 0)
4454 mgmt_pending_remove(cmd);
4455
4456unlock:
4457 hci_dev_unlock(hdev);
4458 return err;
4459}
4460
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004461static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4462 void *data, u16 len)
4463{
4464 struct mgmt_cp_set_static_address *cp = data;
4465 int err;
4466
4467 BT_DBG("%s", hdev->name);
4468
Marcel Holtmann62af4442013-10-02 22:10:32 -07004469 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004470 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004471 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004472
4473 if (hdev_is_powered(hdev))
4474 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4475 MGMT_STATUS_REJECTED);
4476
4477 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4478 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4479 return cmd_status(sk, hdev->id,
4480 MGMT_OP_SET_STATIC_ADDRESS,
4481 MGMT_STATUS_INVALID_PARAMS);
4482
4483 /* Two most significant bits shall be set */
4484 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4485 return cmd_status(sk, hdev->id,
4486 MGMT_OP_SET_STATIC_ADDRESS,
4487 MGMT_STATUS_INVALID_PARAMS);
4488 }
4489
4490 hci_dev_lock(hdev);
4491
4492 bacpy(&hdev->static_addr, &cp->bdaddr);
4493
4494 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4495
4496 hci_dev_unlock(hdev);
4497
4498 return err;
4499}
4500
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004501static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4502 void *data, u16 len)
4503{
4504 struct mgmt_cp_set_scan_params *cp = data;
4505 __u16 interval, window;
4506 int err;
4507
4508 BT_DBG("%s", hdev->name);
4509
4510 if (!lmp_le_capable(hdev))
4511 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4512 MGMT_STATUS_NOT_SUPPORTED);
4513
4514 interval = __le16_to_cpu(cp->interval);
4515
4516 if (interval < 0x0004 || interval > 0x4000)
4517 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4518 MGMT_STATUS_INVALID_PARAMS);
4519
4520 window = __le16_to_cpu(cp->window);
4521
4522 if (window < 0x0004 || window > 0x4000)
4523 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4524 MGMT_STATUS_INVALID_PARAMS);
4525
Marcel Holtmann899e1072013-10-14 09:55:32 -07004526 if (window > interval)
4527 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4528 MGMT_STATUS_INVALID_PARAMS);
4529
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004530 hci_dev_lock(hdev);
4531
4532 hdev->le_scan_interval = interval;
4533 hdev->le_scan_window = window;
4534
4535 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4536
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004537 /* If background scan is running, restart it so new parameters are
4538 * loaded.
4539 */
4540 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4541 hdev->discovery.state == DISCOVERY_STOPPED) {
4542 struct hci_request req;
4543
4544 hci_req_init(&req, hdev);
4545
4546 hci_req_add_le_scan_disable(&req);
4547 hci_req_add_le_passive_scan(&req);
4548
4549 hci_req_run(&req, NULL);
4550 }
4551
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004552 hci_dev_unlock(hdev);
4553
4554 return err;
4555}
4556
Marcel Holtmann1904a852015-01-11 13:50:44 -08004557static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4558 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004559{
4560 struct pending_cmd *cmd;
4561
4562 BT_DBG("status 0x%02x", status);
4563
4564 hci_dev_lock(hdev);
4565
4566 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4567 if (!cmd)
4568 goto unlock;
4569
4570 if (status) {
4571 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4572 mgmt_status(status));
4573 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004574 struct mgmt_mode *cp = cmd->param;
4575
4576 if (cp->val)
4577 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4578 else
4579 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4580
Johan Hedberg33e38b32013-03-15 17:07:05 -05004581 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4582 new_settings(hdev, cmd->sk);
4583 }
4584
4585 mgmt_pending_remove(cmd);
4586
4587unlock:
4588 hci_dev_unlock(hdev);
4589}
4590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004591static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004592 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004593{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004594 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004595 struct pending_cmd *cmd;
4596 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004597 int err;
4598
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004599 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004600
Johan Hedberg56f87902013-10-02 13:43:13 +03004601 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4602 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004603 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4604 MGMT_STATUS_NOT_SUPPORTED);
4605
Johan Hedberga7e80f22013-01-09 16:05:19 +02004606 if (cp->val != 0x00 && cp->val != 0x01)
4607 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4608 MGMT_STATUS_INVALID_PARAMS);
4609
Johan Hedberg5400c042012-02-21 16:40:33 +02004610 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004611 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004612 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004613
4614 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004615 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004616 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004617
4618 hci_dev_lock(hdev);
4619
Johan Hedberg05cbf292013-03-15 17:07:07 -05004620 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4621 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4622 MGMT_STATUS_BUSY);
4623 goto unlock;
4624 }
4625
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004626 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4627 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4628 hdev);
4629 goto unlock;
4630 }
4631
Johan Hedberg33e38b32013-03-15 17:07:05 -05004632 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4633 data, len);
4634 if (!cmd) {
4635 err = -ENOMEM;
4636 goto unlock;
4637 }
4638
4639 hci_req_init(&req, hdev);
4640
Johan Hedberg406d7802013-03-15 17:07:09 -05004641 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004642
4643 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004644 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004645 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004646 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004647 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004648 }
4649
Johan Hedberg33e38b32013-03-15 17:07:05 -05004650unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004651 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004652
Antti Julkuf6422ec2011-06-22 13:11:56 +03004653 return err;
4654}
4655
Marcel Holtmann1904a852015-01-11 13:50:44 -08004656static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004657{
4658 struct pending_cmd *cmd;
4659
4660 BT_DBG("status 0x%02x", status);
4661
4662 hci_dev_lock(hdev);
4663
4664 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4665 if (!cmd)
4666 goto unlock;
4667
4668 if (status) {
4669 u8 mgmt_err = mgmt_status(status);
4670
4671 /* We need to restore the flag if related HCI commands
4672 * failed.
4673 */
4674 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4675
4676 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4677 } else {
4678 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4679 new_settings(hdev, cmd->sk);
4680 }
4681
4682 mgmt_pending_remove(cmd);
4683
4684unlock:
4685 hci_dev_unlock(hdev);
4686}
4687
4688static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4689{
4690 struct mgmt_mode *cp = data;
4691 struct pending_cmd *cmd;
4692 struct hci_request req;
4693 int err;
4694
4695 BT_DBG("request for %s", hdev->name);
4696
4697 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4698 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4699 MGMT_STATUS_NOT_SUPPORTED);
4700
4701 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4702 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4703 MGMT_STATUS_REJECTED);
4704
4705 if (cp->val != 0x00 && cp->val != 0x01)
4706 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4707 MGMT_STATUS_INVALID_PARAMS);
4708
4709 hci_dev_lock(hdev);
4710
4711 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4712 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4713 goto unlock;
4714 }
4715
4716 if (!hdev_is_powered(hdev)) {
4717 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004718 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4719 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4720 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4721 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4722 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4723 }
4724
4725 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4726
4727 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4728 if (err < 0)
4729 goto unlock;
4730
4731 err = new_settings(hdev, sk);
4732 goto unlock;
4733 }
4734
4735 /* Reject disabling when powered on */
4736 if (!cp->val) {
4737 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4738 MGMT_STATUS_REJECTED);
4739 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004740 } else {
4741 /* When configuring a dual-mode controller to operate
4742 * with LE only and using a static address, then switching
4743 * BR/EDR back on is not allowed.
4744 *
4745 * Dual-mode controllers shall operate with the public
4746 * address as its identity address for BR/EDR and LE. So
4747 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004748 *
4749 * The same restrictions applies when secure connections
4750 * has been enabled. For BR/EDR this is a controller feature
4751 * while for LE it is a host stack feature. This means that
4752 * switching BR/EDR back on when secure connections has been
4753 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004754 */
4755 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004756 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4757 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004758 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4759 MGMT_STATUS_REJECTED);
4760 goto unlock;
4761 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004762 }
4763
4764 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4765 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4766 MGMT_STATUS_BUSY);
4767 goto unlock;
4768 }
4769
4770 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4771 if (!cmd) {
4772 err = -ENOMEM;
4773 goto unlock;
4774 }
4775
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004776 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004777 * generates the correct flags.
4778 */
4779 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4780
4781 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004782
Johan Hedberg432df052014-08-01 11:13:31 +03004783 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004784 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004785
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004786 /* Since only the advertising data flags will change, there
4787 * is no need to update the scan response data.
4788 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004789 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004790
Johan Hedberg0663ca22013-10-02 13:43:14 +03004791 err = hci_req_run(&req, set_bredr_complete);
4792 if (err < 0)
4793 mgmt_pending_remove(cmd);
4794
4795unlock:
4796 hci_dev_unlock(hdev);
4797 return err;
4798}
4799
Johan Hedberga1443f52015-01-23 15:42:46 +02004800static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4801{
4802 struct pending_cmd *cmd;
4803 struct mgmt_mode *cp;
4804
4805 BT_DBG("%s status %u", hdev->name, status);
4806
4807 hci_dev_lock(hdev);
4808
4809 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4810 if (!cmd)
4811 goto unlock;
4812
4813 if (status) {
4814 cmd_status(cmd->sk, cmd->index, cmd->opcode,
4815 mgmt_status(status));
4816 goto remove;
4817 }
4818
4819 cp = cmd->param;
4820
4821 switch (cp->val) {
4822 case 0x00:
4823 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4824 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4825 break;
4826 case 0x01:
4827 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4828 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4829 break;
4830 case 0x02:
4831 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4832 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4833 break;
4834 }
4835
4836 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4837 new_settings(hdev, cmd->sk);
4838
4839remove:
4840 mgmt_pending_remove(cmd);
4841unlock:
4842 hci_dev_unlock(hdev);
4843}
4844
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004845static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4846 void *data, u16 len)
4847{
4848 struct mgmt_mode *cp = data;
4849 struct pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004850 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004851 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004852 int err;
4853
4854 BT_DBG("request for %s", hdev->name);
4855
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004856 if (!lmp_sc_capable(hdev) &&
4857 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004858 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4859 MGMT_STATUS_NOT_SUPPORTED);
4860
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004861 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004862 lmp_sc_capable(hdev) &&
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004863 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
4864 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4865 MGMT_STATUS_REJECTED);
4866
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004867 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004868 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4869 MGMT_STATUS_INVALID_PARAMS);
4870
4871 hci_dev_lock(hdev);
4872
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004873 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004874 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004875 bool changed;
4876
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004877 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004878 changed = !test_and_set_bit(HCI_SC_ENABLED,
4879 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004880 if (cp->val == 0x02)
4881 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4882 else
4883 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4884 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004885 changed = test_and_clear_bit(HCI_SC_ENABLED,
4886 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004887 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4888 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004889
4890 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4891 if (err < 0)
4892 goto failed;
4893
4894 if (changed)
4895 err = new_settings(hdev, sk);
4896
4897 goto failed;
4898 }
4899
4900 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4901 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4902 MGMT_STATUS_BUSY);
4903 goto failed;
4904 }
4905
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004906 val = !!cp->val;
4907
4908 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4909 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004910 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4911 goto failed;
4912 }
4913
4914 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4915 if (!cmd) {
4916 err = -ENOMEM;
4917 goto failed;
4918 }
4919
Johan Hedberga1443f52015-01-23 15:42:46 +02004920 hci_req_init(&req, hdev);
4921 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4922 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004923 if (err < 0) {
4924 mgmt_pending_remove(cmd);
4925 goto failed;
4926 }
4927
4928failed:
4929 hci_dev_unlock(hdev);
4930 return err;
4931}
4932
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004933static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4934 void *data, u16 len)
4935{
4936 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004937 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004938 int err;
4939
4940 BT_DBG("request for %s", hdev->name);
4941
Johan Hedbergb97109792014-06-24 14:00:28 +03004942 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004943 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4944 MGMT_STATUS_INVALID_PARAMS);
4945
4946 hci_dev_lock(hdev);
4947
4948 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004949 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4950 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004951 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004952 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4953 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004954
Johan Hedbergb97109792014-06-24 14:00:28 +03004955 if (cp->val == 0x02)
4956 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4957 &hdev->dev_flags);
4958 else
4959 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4960 &hdev->dev_flags);
4961
4962 if (hdev_is_powered(hdev) && use_changed &&
4963 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4964 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4965 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4966 sizeof(mode), &mode);
4967 }
4968
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004969 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4970 if (err < 0)
4971 goto unlock;
4972
4973 if (changed)
4974 err = new_settings(hdev, sk);
4975
4976unlock:
4977 hci_dev_unlock(hdev);
4978 return err;
4979}
4980
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004981static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4982 u16 len)
4983{
4984 struct mgmt_cp_set_privacy *cp = cp_data;
4985 bool changed;
4986 int err;
4987
4988 BT_DBG("request for %s", hdev->name);
4989
4990 if (!lmp_le_capable(hdev))
4991 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4992 MGMT_STATUS_NOT_SUPPORTED);
4993
4994 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4995 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4996 MGMT_STATUS_INVALID_PARAMS);
4997
4998 if (hdev_is_powered(hdev))
4999 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5000 MGMT_STATUS_REJECTED);
5001
5002 hci_dev_lock(hdev);
5003
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005004 /* If user space supports this command it is also expected to
5005 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5006 */
5007 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5008
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005009 if (cp->privacy) {
5010 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5011 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5012 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5013 } else {
5014 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5015 memset(hdev->irk, 0, sizeof(hdev->irk));
5016 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5017 }
5018
5019 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5020 if (err < 0)
5021 goto unlock;
5022
5023 if (changed)
5024 err = new_settings(hdev, sk);
5025
5026unlock:
5027 hci_dev_unlock(hdev);
5028 return err;
5029}
5030
Johan Hedberg41edf162014-02-18 10:19:35 +02005031static bool irk_is_valid(struct mgmt_irk_info *irk)
5032{
5033 switch (irk->addr.type) {
5034 case BDADDR_LE_PUBLIC:
5035 return true;
5036
5037 case BDADDR_LE_RANDOM:
5038 /* Two most significant bits shall be set */
5039 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5040 return false;
5041 return true;
5042 }
5043
5044 return false;
5045}
5046
5047static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5048 u16 len)
5049{
5050 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005051 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5052 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005053 u16 irk_count, expected_len;
5054 int i, err;
5055
5056 BT_DBG("request for %s", hdev->name);
5057
5058 if (!lmp_le_capable(hdev))
5059 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5060 MGMT_STATUS_NOT_SUPPORTED);
5061
5062 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005063 if (irk_count > max_irk_count) {
5064 BT_ERR("load_irks: too big irk_count value %u", irk_count);
5065 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5066 MGMT_STATUS_INVALID_PARAMS);
5067 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005068
5069 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5070 if (expected_len != len) {
5071 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005072 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02005073 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5074 MGMT_STATUS_INVALID_PARAMS);
5075 }
5076
5077 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5078
5079 for (i = 0; i < irk_count; i++) {
5080 struct mgmt_irk_info *key = &cp->irks[i];
5081
5082 if (!irk_is_valid(key))
5083 return cmd_status(sk, hdev->id,
5084 MGMT_OP_LOAD_IRKS,
5085 MGMT_STATUS_INVALID_PARAMS);
5086 }
5087
5088 hci_dev_lock(hdev);
5089
5090 hci_smp_irks_clear(hdev);
5091
5092 for (i = 0; i < irk_count; i++) {
5093 struct mgmt_irk_info *irk = &cp->irks[i];
5094 u8 addr_type;
5095
5096 if (irk->addr.type == BDADDR_LE_PUBLIC)
5097 addr_type = ADDR_LE_DEV_PUBLIC;
5098 else
5099 addr_type = ADDR_LE_DEV_RANDOM;
5100
5101 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5102 BDADDR_ANY);
5103 }
5104
5105 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5106
5107 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
5108
5109 hci_dev_unlock(hdev);
5110
5111 return err;
5112}
5113
Johan Hedberg3f706b72013-01-20 14:27:16 +02005114static bool ltk_is_valid(struct mgmt_ltk_info *key)
5115{
5116 if (key->master != 0x00 && key->master != 0x01)
5117 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005118
5119 switch (key->addr.type) {
5120 case BDADDR_LE_PUBLIC:
5121 return true;
5122
5123 case BDADDR_LE_RANDOM:
5124 /* Two most significant bits shall be set */
5125 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5126 return false;
5127 return true;
5128 }
5129
5130 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005131}
5132
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005133static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005134 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005135{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005136 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005137 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5138 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005139 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005140 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005141
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005142 BT_DBG("request for %s", hdev->name);
5143
5144 if (!lmp_le_capable(hdev))
5145 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5146 MGMT_STATUS_NOT_SUPPORTED);
5147
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005148 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005149 if (key_count > max_key_count) {
5150 BT_ERR("load_ltks: too big key_count value %u", key_count);
5151 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5152 MGMT_STATUS_INVALID_PARAMS);
5153 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005154
5155 expected_len = sizeof(*cp) + key_count *
5156 sizeof(struct mgmt_ltk_info);
5157 if (expected_len != len) {
5158 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005159 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005160 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005161 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005162 }
5163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005164 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005165
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005166 for (i = 0; i < key_count; i++) {
5167 struct mgmt_ltk_info *key = &cp->keys[i];
5168
Johan Hedberg3f706b72013-01-20 14:27:16 +02005169 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005170 return cmd_status(sk, hdev->id,
5171 MGMT_OP_LOAD_LONG_TERM_KEYS,
5172 MGMT_STATUS_INVALID_PARAMS);
5173 }
5174
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005175 hci_dev_lock(hdev);
5176
5177 hci_smp_ltks_clear(hdev);
5178
5179 for (i = 0; i < key_count; i++) {
5180 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005181 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005182
5183 if (key->addr.type == BDADDR_LE_PUBLIC)
5184 addr_type = ADDR_LE_DEV_PUBLIC;
5185 else
5186 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005187
Johan Hedberg61b43352014-05-29 19:36:53 +03005188 switch (key->type) {
5189 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005190 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005191 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005192 break;
5193 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005194 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005195 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005196 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005197 case MGMT_LTK_P256_UNAUTH:
5198 authenticated = 0x00;
5199 type = SMP_LTK_P256;
5200 break;
5201 case MGMT_LTK_P256_AUTH:
5202 authenticated = 0x01;
5203 type = SMP_LTK_P256;
5204 break;
5205 case MGMT_LTK_P256_DEBUG:
5206 authenticated = 0x00;
5207 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005208 default:
5209 continue;
5210 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005211
Johan Hedberg35d70272014-02-19 14:57:47 +02005212 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005213 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005214 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005215 }
5216
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005217 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5218 NULL, 0);
5219
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005220 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005221
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005222 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005223}
5224
Johan Hedberg9df74652014-12-19 22:26:03 +02005225static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005226{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005227 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005228 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005229 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005230
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005231 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005232
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005233 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005234 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005235 rp.tx_power = conn->tx_power;
5236 rp.max_tx_power = conn->max_tx_power;
5237 } else {
5238 rp.rssi = HCI_RSSI_INVALID;
5239 rp.tx_power = HCI_TX_POWER_INVALID;
5240 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005241 }
5242
Johan Hedberg9df74652014-12-19 22:26:03 +02005243 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5244 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005245
5246 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005247 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005248
5249 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005250}
5251
Marcel Holtmann1904a852015-01-11 13:50:44 -08005252static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5253 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005254{
5255 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005256 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005257 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005258 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005259 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005260
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005261 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005262
5263 hci_dev_lock(hdev);
5264
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005265 /* Commands sent in request are either Read RSSI or Read Transmit Power
5266 * Level so we check which one was last sent to retrieve connection
5267 * handle. Both commands have handle as first parameter so it's safe to
5268 * cast data on the same command struct.
5269 *
5270 * First command sent is always Read RSSI and we fail only if it fails.
5271 * In other case we simply override error to indicate success as we
5272 * already remembered if TX power value is actually valid.
5273 */
5274 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5275 if (!cp) {
5276 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005277 status = MGMT_STATUS_SUCCESS;
5278 } else {
5279 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005280 }
5281
5282 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005283 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005284 goto unlock;
5285 }
5286
5287 handle = __le16_to_cpu(cp->handle);
5288 conn = hci_conn_hash_lookup_handle(hdev, handle);
5289 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005290 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005291 goto unlock;
5292 }
5293
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005294 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5295 if (!cmd)
5296 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005297
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005298 cmd->cmd_complete(cmd, status);
5299 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005300
5301unlock:
5302 hci_dev_unlock(hdev);
5303}
5304
5305static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5306 u16 len)
5307{
5308 struct mgmt_cp_get_conn_info *cp = data;
5309 struct mgmt_rp_get_conn_info rp;
5310 struct hci_conn *conn;
5311 unsigned long conn_info_age;
5312 int err = 0;
5313
5314 BT_DBG("%s", hdev->name);
5315
5316 memset(&rp, 0, sizeof(rp));
5317 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5318 rp.addr.type = cp->addr.type;
5319
5320 if (!bdaddr_type_is_valid(cp->addr.type))
5321 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5322 MGMT_STATUS_INVALID_PARAMS,
5323 &rp, sizeof(rp));
5324
5325 hci_dev_lock(hdev);
5326
5327 if (!hdev_is_powered(hdev)) {
5328 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5329 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5330 goto unlock;
5331 }
5332
5333 if (cp->addr.type == BDADDR_BREDR)
5334 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5335 &cp->addr.bdaddr);
5336 else
5337 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5338
5339 if (!conn || conn->state != BT_CONNECTED) {
5340 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5341 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5342 goto unlock;
5343 }
5344
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005345 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5346 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5347 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5348 goto unlock;
5349 }
5350
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005351 /* To avoid client trying to guess when to poll again for information we
5352 * calculate conn info age as random value between min/max set in hdev.
5353 */
5354 conn_info_age = hdev->conn_info_min_age +
5355 prandom_u32_max(hdev->conn_info_max_age -
5356 hdev->conn_info_min_age);
5357
5358 /* Query controller to refresh cached values if they are too old or were
5359 * never read.
5360 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005361 if (time_after(jiffies, conn->conn_info_timestamp +
5362 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005363 !conn->conn_info_timestamp) {
5364 struct hci_request req;
5365 struct hci_cp_read_tx_power req_txp_cp;
5366 struct hci_cp_read_rssi req_rssi_cp;
5367 struct pending_cmd *cmd;
5368
5369 hci_req_init(&req, hdev);
5370 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5371 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5372 &req_rssi_cp);
5373
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005374 /* For LE links TX power does not change thus we don't need to
5375 * query for it once value is known.
5376 */
5377 if (!bdaddr_type_is_le(cp->addr.type) ||
5378 conn->tx_power == HCI_TX_POWER_INVALID) {
5379 req_txp_cp.handle = cpu_to_le16(conn->handle);
5380 req_txp_cp.type = 0x00;
5381 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5382 sizeof(req_txp_cp), &req_txp_cp);
5383 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005384
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005385 /* Max TX power needs to be read only once per connection */
5386 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5387 req_txp_cp.handle = cpu_to_le16(conn->handle);
5388 req_txp_cp.type = 0x01;
5389 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5390 sizeof(req_txp_cp), &req_txp_cp);
5391 }
5392
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005393 err = hci_req_run(&req, conn_info_refresh_complete);
5394 if (err < 0)
5395 goto unlock;
5396
5397 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5398 data, len);
5399 if (!cmd) {
5400 err = -ENOMEM;
5401 goto unlock;
5402 }
5403
5404 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005405 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005406 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005407
5408 conn->conn_info_timestamp = jiffies;
5409 } else {
5410 /* Cache is valid, just reply with values cached in hci_conn */
5411 rp.rssi = conn->rssi;
5412 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005413 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005414
5415 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5416 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5417 }
5418
5419unlock:
5420 hci_dev_unlock(hdev);
5421 return err;
5422}
5423
Johan Hedberg9df74652014-12-19 22:26:03 +02005424static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005425{
5426 struct hci_conn *conn = cmd->user_data;
5427 struct mgmt_rp_get_clock_info rp;
5428 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005429 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005430
5431 memset(&rp, 0, sizeof(rp));
5432 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5433
5434 if (status)
5435 goto complete;
5436
5437 hdev = hci_dev_get(cmd->index);
5438 if (hdev) {
5439 rp.local_clock = cpu_to_le32(hdev->clock);
5440 hci_dev_put(hdev);
5441 }
5442
5443 if (conn) {
5444 rp.piconet_clock = cpu_to_le32(conn->clock);
5445 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5446 }
5447
5448complete:
Johan Hedberg9df74652014-12-19 22:26:03 +02005449 err = cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5450 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005451
5452 if (conn) {
5453 hci_conn_drop(conn);
5454 hci_conn_put(conn);
5455 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005456
5457 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005458}
5459
Marcel Holtmann1904a852015-01-11 13:50:44 -08005460static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005461{
Johan Hedberg95868422014-06-28 17:54:07 +03005462 struct hci_cp_read_clock *hci_cp;
5463 struct pending_cmd *cmd;
5464 struct hci_conn *conn;
5465
5466 BT_DBG("%s status %u", hdev->name, status);
5467
5468 hci_dev_lock(hdev);
5469
5470 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5471 if (!hci_cp)
5472 goto unlock;
5473
5474 if (hci_cp->which) {
5475 u16 handle = __le16_to_cpu(hci_cp->handle);
5476 conn = hci_conn_hash_lookup_handle(hdev, handle);
5477 } else {
5478 conn = NULL;
5479 }
5480
5481 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5482 if (!cmd)
5483 goto unlock;
5484
Johan Hedberg69487372014-12-05 13:36:07 +02005485 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005486 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005487
5488unlock:
5489 hci_dev_unlock(hdev);
5490}
5491
5492static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5493 u16 len)
5494{
5495 struct mgmt_cp_get_clock_info *cp = data;
5496 struct mgmt_rp_get_clock_info rp;
5497 struct hci_cp_read_clock hci_cp;
5498 struct pending_cmd *cmd;
5499 struct hci_request req;
5500 struct hci_conn *conn;
5501 int err;
5502
5503 BT_DBG("%s", hdev->name);
5504
5505 memset(&rp, 0, sizeof(rp));
5506 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5507 rp.addr.type = cp->addr.type;
5508
5509 if (cp->addr.type != BDADDR_BREDR)
5510 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5511 MGMT_STATUS_INVALID_PARAMS,
5512 &rp, sizeof(rp));
5513
5514 hci_dev_lock(hdev);
5515
5516 if (!hdev_is_powered(hdev)) {
5517 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5518 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5519 goto unlock;
5520 }
5521
5522 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5523 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5524 &cp->addr.bdaddr);
5525 if (!conn || conn->state != BT_CONNECTED) {
5526 err = cmd_complete(sk, hdev->id,
5527 MGMT_OP_GET_CLOCK_INFO,
5528 MGMT_STATUS_NOT_CONNECTED,
5529 &rp, sizeof(rp));
5530 goto unlock;
5531 }
5532 } else {
5533 conn = NULL;
5534 }
5535
5536 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5537 if (!cmd) {
5538 err = -ENOMEM;
5539 goto unlock;
5540 }
5541
Johan Hedberg69487372014-12-05 13:36:07 +02005542 cmd->cmd_complete = clock_info_cmd_complete;
5543
Johan Hedberg95868422014-06-28 17:54:07 +03005544 hci_req_init(&req, hdev);
5545
5546 memset(&hci_cp, 0, sizeof(hci_cp));
5547 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5548
5549 if (conn) {
5550 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005551 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005552
5553 hci_cp.handle = cpu_to_le16(conn->handle);
5554 hci_cp.which = 0x01; /* Piconet clock */
5555 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5556 }
5557
5558 err = hci_req_run(&req, get_clock_info_complete);
5559 if (err < 0)
5560 mgmt_pending_remove(cmd);
5561
5562unlock:
5563 hci_dev_unlock(hdev);
5564 return err;
5565}
5566
Johan Hedberg5a154e62014-12-19 22:26:02 +02005567static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5568{
5569 struct hci_conn *conn;
5570
5571 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5572 if (!conn)
5573 return false;
5574
5575 if (conn->dst_type != type)
5576 return false;
5577
5578 if (conn->state != BT_CONNECTED)
5579 return false;
5580
5581 return true;
5582}
5583
5584/* This function requires the caller holds hdev->lock */
5585static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5586 u8 addr_type, u8 auto_connect)
5587{
5588 struct hci_dev *hdev = req->hdev;
5589 struct hci_conn_params *params;
5590
5591 params = hci_conn_params_add(hdev, addr, addr_type);
5592 if (!params)
5593 return -EIO;
5594
5595 if (params->auto_connect == auto_connect)
5596 return 0;
5597
5598 list_del_init(&params->action);
5599
5600 switch (auto_connect) {
5601 case HCI_AUTO_CONN_DISABLED:
5602 case HCI_AUTO_CONN_LINK_LOSS:
5603 __hci_update_background_scan(req);
5604 break;
5605 case HCI_AUTO_CONN_REPORT:
5606 list_add(&params->action, &hdev->pend_le_reports);
5607 __hci_update_background_scan(req);
5608 break;
5609 case HCI_AUTO_CONN_DIRECT:
5610 case HCI_AUTO_CONN_ALWAYS:
5611 if (!is_connected(hdev, addr, addr_type)) {
5612 list_add(&params->action, &hdev->pend_le_conns);
5613 __hci_update_background_scan(req);
5614 }
5615 break;
5616 }
5617
5618 params->auto_connect = auto_connect;
5619
5620 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5621 auto_connect);
5622
5623 return 0;
5624}
5625
Marcel Holtmann8afef092014-06-29 22:28:34 +02005626static void device_added(struct sock *sk, struct hci_dev *hdev,
5627 bdaddr_t *bdaddr, u8 type, u8 action)
5628{
5629 struct mgmt_ev_device_added ev;
5630
5631 bacpy(&ev.addr.bdaddr, bdaddr);
5632 ev.addr.type = type;
5633 ev.action = action;
5634
5635 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5636}
5637
Marcel Holtmann1904a852015-01-11 13:50:44 -08005638static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005639{
5640 struct pending_cmd *cmd;
5641
5642 BT_DBG("status 0x%02x", status);
5643
5644 hci_dev_lock(hdev);
5645
5646 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5647 if (!cmd)
5648 goto unlock;
5649
5650 cmd->cmd_complete(cmd, mgmt_status(status));
5651 mgmt_pending_remove(cmd);
5652
5653unlock:
5654 hci_dev_unlock(hdev);
5655}
5656
Marcel Holtmann2faade52014-06-29 19:44:03 +02005657static int add_device(struct sock *sk, struct hci_dev *hdev,
5658 void *data, u16 len)
5659{
5660 struct mgmt_cp_add_device *cp = data;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005661 struct pending_cmd *cmd;
5662 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005663 u8 auto_conn, addr_type;
5664 int err;
5665
5666 BT_DBG("%s", hdev->name);
5667
Johan Hedberg66593582014-07-09 12:59:14 +03005668 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005669 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5670 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5671 MGMT_STATUS_INVALID_PARAMS,
5672 &cp->addr, sizeof(cp->addr));
5673
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005674 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005675 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5676 MGMT_STATUS_INVALID_PARAMS,
5677 &cp->addr, sizeof(cp->addr));
5678
Johan Hedberg5a154e62014-12-19 22:26:02 +02005679 hci_req_init(&req, hdev);
5680
Marcel Holtmann2faade52014-06-29 19:44:03 +02005681 hci_dev_lock(hdev);
5682
Johan Hedberg5a154e62014-12-19 22:26:02 +02005683 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5684 if (!cmd) {
5685 err = -ENOMEM;
5686 goto unlock;
5687 }
5688
5689 cmd->cmd_complete = addr_cmd_complete;
5690
Johan Hedberg66593582014-07-09 12:59:14 +03005691 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005692 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005693 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005694 err = cmd->cmd_complete(cmd,
5695 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005696 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005697 goto unlock;
5698 }
5699
5700 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5701 cp->addr.type);
5702 if (err)
5703 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005704
Johan Hedberg5a154e62014-12-19 22:26:02 +02005705 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005706
Johan Hedberg66593582014-07-09 12:59:14 +03005707 goto added;
5708 }
5709
Marcel Holtmann2faade52014-06-29 19:44:03 +02005710 if (cp->addr.type == BDADDR_LE_PUBLIC)
5711 addr_type = ADDR_LE_DEV_PUBLIC;
5712 else
5713 addr_type = ADDR_LE_DEV_RANDOM;
5714
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005715 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005716 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005717 else if (cp->action == 0x01)
5718 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005719 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005720 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005721
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005722 /* If the connection parameters don't exist for this device,
5723 * they will be created and configured with defaults.
5724 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005725 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005726 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005727 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005728 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005729 goto unlock;
5730 }
5731
Johan Hedberg66593582014-07-09 12:59:14 +03005732added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005733 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5734
Johan Hedberg5a154e62014-12-19 22:26:02 +02005735 err = hci_req_run(&req, add_device_complete);
5736 if (err < 0) {
5737 /* ENODATA means no HCI commands were needed (e.g. if
5738 * the adapter is powered off).
5739 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005740 if (err == -ENODATA)
5741 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005742 mgmt_pending_remove(cmd);
5743 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005744
5745unlock:
5746 hci_dev_unlock(hdev);
5747 return err;
5748}
5749
Marcel Holtmann8afef092014-06-29 22:28:34 +02005750static void device_removed(struct sock *sk, struct hci_dev *hdev,
5751 bdaddr_t *bdaddr, u8 type)
5752{
5753 struct mgmt_ev_device_removed ev;
5754
5755 bacpy(&ev.addr.bdaddr, bdaddr);
5756 ev.addr.type = type;
5757
5758 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5759}
5760
Marcel Holtmann1904a852015-01-11 13:50:44 -08005761static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005762{
5763 struct pending_cmd *cmd;
5764
5765 BT_DBG("status 0x%02x", status);
5766
5767 hci_dev_lock(hdev);
5768
5769 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5770 if (!cmd)
5771 goto unlock;
5772
5773 cmd->cmd_complete(cmd, mgmt_status(status));
5774 mgmt_pending_remove(cmd);
5775
5776unlock:
5777 hci_dev_unlock(hdev);
5778}
5779
Marcel Holtmann2faade52014-06-29 19:44:03 +02005780static int remove_device(struct sock *sk, struct hci_dev *hdev,
5781 void *data, u16 len)
5782{
5783 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005784 struct pending_cmd *cmd;
5785 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005786 int err;
5787
5788 BT_DBG("%s", hdev->name);
5789
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005790 hci_req_init(&req, hdev);
5791
Marcel Holtmann2faade52014-06-29 19:44:03 +02005792 hci_dev_lock(hdev);
5793
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005794 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5795 if (!cmd) {
5796 err = -ENOMEM;
5797 goto unlock;
5798 }
5799
5800 cmd->cmd_complete = addr_cmd_complete;
5801
Marcel Holtmann2faade52014-06-29 19:44:03 +02005802 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005803 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005804 u8 addr_type;
5805
Johan Hedberg66593582014-07-09 12:59:14 +03005806 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005807 err = cmd->cmd_complete(cmd,
5808 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005809 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005810 goto unlock;
5811 }
5812
Johan Hedberg66593582014-07-09 12:59:14 +03005813 if (cp->addr.type == BDADDR_BREDR) {
5814 err = hci_bdaddr_list_del(&hdev->whitelist,
5815 &cp->addr.bdaddr,
5816 cp->addr.type);
5817 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005818 err = cmd->cmd_complete(cmd,
5819 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005820 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005821 goto unlock;
5822 }
5823
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005824 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005825
Johan Hedberg66593582014-07-09 12:59:14 +03005826 device_removed(sk, hdev, &cp->addr.bdaddr,
5827 cp->addr.type);
5828 goto complete;
5829 }
5830
Marcel Holtmann2faade52014-06-29 19:44:03 +02005831 if (cp->addr.type == BDADDR_LE_PUBLIC)
5832 addr_type = ADDR_LE_DEV_PUBLIC;
5833 else
5834 addr_type = ADDR_LE_DEV_RANDOM;
5835
Johan Hedbergc71593d2014-07-02 17:37:28 +03005836 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5837 addr_type);
5838 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005839 err = cmd->cmd_complete(cmd,
5840 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005841 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005842 goto unlock;
5843 }
5844
5845 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005846 err = cmd->cmd_complete(cmd,
5847 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005848 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005849 goto unlock;
5850 }
5851
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005852 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005853 list_del(&params->list);
5854 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005855 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005856
5857 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005858 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005859 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005860 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005861
Marcel Holtmann2faade52014-06-29 19:44:03 +02005862 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005863 err = cmd->cmd_complete(cmd,
5864 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005865 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005866 goto unlock;
5867 }
5868
Johan Hedberg66593582014-07-09 12:59:14 +03005869 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5870 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5871 list_del(&b->list);
5872 kfree(b);
5873 }
5874
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005875 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005876
Johan Hedberg19de0822014-07-06 13:06:51 +03005877 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5878 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5879 continue;
5880 device_removed(sk, hdev, &p->addr, p->addr_type);
5881 list_del(&p->action);
5882 list_del(&p->list);
5883 kfree(p);
5884 }
5885
5886 BT_DBG("All LE connection parameters were removed");
5887
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005888 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005889 }
5890
Johan Hedberg66593582014-07-09 12:59:14 +03005891complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005892 err = hci_req_run(&req, remove_device_complete);
5893 if (err < 0) {
5894 /* ENODATA means no HCI commands were needed (e.g. if
5895 * the adapter is powered off).
5896 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005897 if (err == -ENODATA)
5898 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005899 mgmt_pending_remove(cmd);
5900 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005901
5902unlock:
5903 hci_dev_unlock(hdev);
5904 return err;
5905}
5906
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005907static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5908 u16 len)
5909{
5910 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005911 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5912 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005913 u16 param_count, expected_len;
5914 int i;
5915
5916 if (!lmp_le_capable(hdev))
5917 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5918 MGMT_STATUS_NOT_SUPPORTED);
5919
5920 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005921 if (param_count > max_param_count) {
5922 BT_ERR("load_conn_param: too big param_count value %u",
5923 param_count);
5924 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5925 MGMT_STATUS_INVALID_PARAMS);
5926 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005927
5928 expected_len = sizeof(*cp) + param_count *
5929 sizeof(struct mgmt_conn_param);
5930 if (expected_len != len) {
5931 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5932 expected_len, len);
5933 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5934 MGMT_STATUS_INVALID_PARAMS);
5935 }
5936
5937 BT_DBG("%s param_count %u", hdev->name, param_count);
5938
5939 hci_dev_lock(hdev);
5940
5941 hci_conn_params_clear_disabled(hdev);
5942
5943 for (i = 0; i < param_count; i++) {
5944 struct mgmt_conn_param *param = &cp->params[i];
5945 struct hci_conn_params *hci_param;
5946 u16 min, max, latency, timeout;
5947 u8 addr_type;
5948
5949 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5950 param->addr.type);
5951
5952 if (param->addr.type == BDADDR_LE_PUBLIC) {
5953 addr_type = ADDR_LE_DEV_PUBLIC;
5954 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5955 addr_type = ADDR_LE_DEV_RANDOM;
5956 } else {
5957 BT_ERR("Ignoring invalid connection parameters");
5958 continue;
5959 }
5960
5961 min = le16_to_cpu(param->min_interval);
5962 max = le16_to_cpu(param->max_interval);
5963 latency = le16_to_cpu(param->latency);
5964 timeout = le16_to_cpu(param->timeout);
5965
5966 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5967 min, max, latency, timeout);
5968
5969 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5970 BT_ERR("Ignoring invalid connection parameters");
5971 continue;
5972 }
5973
5974 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5975 addr_type);
5976 if (!hci_param) {
5977 BT_ERR("Failed to add connection parameters");
5978 continue;
5979 }
5980
5981 hci_param->conn_min_interval = min;
5982 hci_param->conn_max_interval = max;
5983 hci_param->conn_latency = latency;
5984 hci_param->supervision_timeout = timeout;
5985 }
5986
5987 hci_dev_unlock(hdev);
5988
5989 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5990}
5991
Marcel Holtmanndbece372014-07-04 18:11:55 +02005992static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5993 void *data, u16 len)
5994{
5995 struct mgmt_cp_set_external_config *cp = data;
5996 bool changed;
5997 int err;
5998
5999 BT_DBG("%s", hdev->name);
6000
6001 if (hdev_is_powered(hdev))
6002 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6003 MGMT_STATUS_REJECTED);
6004
6005 if (cp->config != 0x00 && cp->config != 0x01)
6006 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6007 MGMT_STATUS_INVALID_PARAMS);
6008
6009 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
6010 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6011 MGMT_STATUS_NOT_SUPPORTED);
6012
6013 hci_dev_lock(hdev);
6014
6015 if (cp->config)
6016 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6017 &hdev->dev_flags);
6018 else
6019 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6020 &hdev->dev_flags);
6021
6022 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6023 if (err < 0)
6024 goto unlock;
6025
6026 if (!changed)
6027 goto unlock;
6028
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006029 err = new_options(hdev, sk);
6030
Marcel Holtmanndbece372014-07-04 18:11:55 +02006031 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
6032 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006033
6034 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6035 set_bit(HCI_CONFIG, &hdev->dev_flags);
6036 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6037
6038 queue_work(hdev->req_workqueue, &hdev->power_on);
6039 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006040 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006041 mgmt_index_added(hdev);
6042 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006043 }
6044
6045unlock:
6046 hci_dev_unlock(hdev);
6047 return err;
6048}
6049
Marcel Holtmann9713c172014-07-06 12:11:15 +02006050static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6051 void *data, u16 len)
6052{
6053 struct mgmt_cp_set_public_address *cp = data;
6054 bool changed;
6055 int err;
6056
6057 BT_DBG("%s", hdev->name);
6058
6059 if (hdev_is_powered(hdev))
6060 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6061 MGMT_STATUS_REJECTED);
6062
6063 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
6064 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6065 MGMT_STATUS_INVALID_PARAMS);
6066
6067 if (!hdev->set_bdaddr)
6068 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6069 MGMT_STATUS_NOT_SUPPORTED);
6070
6071 hci_dev_lock(hdev);
6072
6073 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6074 bacpy(&hdev->public_addr, &cp->bdaddr);
6075
6076 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6077 if (err < 0)
6078 goto unlock;
6079
6080 if (!changed)
6081 goto unlock;
6082
6083 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6084 err = new_options(hdev, sk);
6085
6086 if (is_configured(hdev)) {
6087 mgmt_index_removed(hdev);
6088
6089 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6090
6091 set_bit(HCI_CONFIG, &hdev->dev_flags);
6092 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6093
6094 queue_work(hdev->req_workqueue, &hdev->power_on);
6095 }
6096
6097unlock:
6098 hci_dev_unlock(hdev);
6099 return err;
6100}
6101
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006102static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006103 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
6104 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006105 bool var_len;
6106 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006107} mgmt_handlers[] = {
6108 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02006109 { read_version, false, MGMT_READ_VERSION_SIZE },
6110 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
6111 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
6112 { read_controller_info, false, MGMT_READ_INFO_SIZE },
6113 { set_powered, false, MGMT_SETTING_SIZE },
6114 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
6115 { set_connectable, false, MGMT_SETTING_SIZE },
6116 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03006117 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006118 { set_link_security, false, MGMT_SETTING_SIZE },
6119 { set_ssp, false, MGMT_SETTING_SIZE },
6120 { set_hs, false, MGMT_SETTING_SIZE },
6121 { set_le, false, MGMT_SETTING_SIZE },
6122 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
6123 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
6124 { add_uuid, false, MGMT_ADD_UUID_SIZE },
6125 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
6126 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
6127 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
6128 { disconnect, false, MGMT_DISCONNECT_SIZE },
6129 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
6130 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
6131 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6132 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
6133 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
6134 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6135 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
6136 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
6137 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6138 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
6139 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
6140 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08006141 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006142 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6143 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
6144 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
6145 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
6146 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
6147 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07006148 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03006149 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03006150 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006151 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07006152 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006153 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08006154 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02006155 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02006156 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02006157 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03006158 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02006159 { add_device, false, MGMT_ADD_DEVICE_SIZE },
6160 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006161 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
6162 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02006163 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02006164 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02006165 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01006166 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006167};
6168
Johan Hedberg03811012010-12-08 00:21:06 +02006169int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
6170{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006171 void *buf;
6172 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006173 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006174 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006175 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006176 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02006177 int err;
6178
6179 BT_DBG("got %zu bytes", msglen);
6180
6181 if (msglen < sizeof(*hdr))
6182 return -EINVAL;
6183
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006184 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006185 if (!buf)
6186 return -ENOMEM;
6187
Al Viro6ce8e9c2014-04-06 21:25:44 -04006188 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006189 err = -EFAULT;
6190 goto done;
6191 }
6192
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006193 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006194 opcode = __le16_to_cpu(hdr->opcode);
6195 index = __le16_to_cpu(hdr->index);
6196 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006197
6198 if (len != msglen - sizeof(*hdr)) {
6199 err = -EINVAL;
6200 goto done;
6201 }
6202
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006203 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006204 hdev = hci_dev_get(index);
6205 if (!hdev) {
6206 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006207 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006208 goto done;
6209 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006210
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006211 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006212 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006213 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006214 err = cmd_status(sk, index, opcode,
6215 MGMT_STATUS_INVALID_INDEX);
6216 goto done;
6217 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006218
6219 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02006220 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02006221 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
6222 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006223 err = cmd_status(sk, index, opcode,
6224 MGMT_STATUS_INVALID_INDEX);
6225 goto done;
6226 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006227 }
6228
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006229 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006230 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02006231 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02006232 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006233 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006234 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02006235 }
6236
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006237 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
6238 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
6239 err = cmd_status(sk, index, opcode,
6240 MGMT_STATUS_INVALID_INDEX);
6241 goto done;
6242 }
6243
6244 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
6245 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006246 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006247 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006248 goto done;
6249 }
6250
Johan Hedbergbe22b542012-03-01 22:24:41 +02006251 handler = &mgmt_handlers[opcode];
6252
6253 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006254 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02006255 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006256 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006257 goto done;
6258 }
6259
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006260 if (hdev)
6261 mgmt_init_hdev(sk, hdev);
6262
6263 cp = buf + sizeof(*hdr);
6264
Johan Hedbergbe22b542012-03-01 22:24:41 +02006265 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006266 if (err < 0)
6267 goto done;
6268
Johan Hedberg03811012010-12-08 00:21:06 +02006269 err = msglen;
6270
6271done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006272 if (hdev)
6273 hci_dev_put(hdev);
6274
Johan Hedberg03811012010-12-08 00:21:06 +02006275 kfree(buf);
6276 return err;
6277}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006278
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006279void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006280{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006281 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006282 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006283
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006284 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6285 return;
6286
6287 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6288 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6289 else
6290 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006291}
6292
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006293void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006294{
Johan Hedberg5f159032012-03-02 03:13:19 +02006295 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006296
Marcel Holtmann1514b892013-10-06 08:25:01 -07006297 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006298 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006299
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006300 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6301 return;
6302
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006303 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006304
Marcel Holtmannedd38962014-07-02 21:30:55 +02006305 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6306 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6307 else
6308 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006309}
6310
Andre Guedes6046dc32014-02-26 20:21:51 -03006311/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006312static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006313{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006314 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006315 struct hci_conn_params *p;
6316
6317 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006318 /* Needed for AUTO_OFF case where might not "really"
6319 * have been powered off.
6320 */
6321 list_del_init(&p->action);
6322
6323 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006324 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006325 case HCI_AUTO_CONN_ALWAYS:
6326 list_add(&p->action, &hdev->pend_le_conns);
6327 break;
6328 case HCI_AUTO_CONN_REPORT:
6329 list_add(&p->action, &hdev->pend_le_reports);
6330 break;
6331 default:
6332 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006333 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006334 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006335
Johan Hedberg2cf22212014-12-19 22:26:00 +02006336 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006337}
6338
Marcel Holtmann1904a852015-01-11 13:50:44 -08006339static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006340{
6341 struct cmd_lookup match = { NULL, hdev };
6342
6343 BT_DBG("status 0x%02x", status);
6344
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006345 if (!status) {
6346 /* Register the available SMP channels (BR/EDR and LE) only
6347 * when successfully powering on the controller. This late
6348 * registration is required so that LE SMP can clearly
6349 * decide if the public address or static address is used.
6350 */
6351 smp_register(hdev);
6352 }
6353
Johan Hedberg229ab392013-03-15 17:06:53 -05006354 hci_dev_lock(hdev);
6355
6356 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6357
6358 new_settings(hdev, match.sk);
6359
6360 hci_dev_unlock(hdev);
6361
6362 if (match.sk)
6363 sock_put(match.sk);
6364}
6365
Johan Hedberg70da6242013-03-15 17:06:51 -05006366static int powered_update_hci(struct hci_dev *hdev)
6367{
Johan Hedberg890ea892013-03-15 17:06:52 -05006368 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006369 u8 link_sec;
6370
Johan Hedberg890ea892013-03-15 17:06:52 -05006371 hci_req_init(&req, hdev);
6372
Johan Hedberg70da6242013-03-15 17:06:51 -05006373 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6374 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006375 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006376
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006377 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006378
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006379 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6380 u8 support = 0x01;
6381
6382 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6383 sizeof(support), &support);
6384 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006385 }
6386
Johan Hedbergc73eee92013-04-19 18:35:21 +03006387 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6388 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006389 struct hci_cp_write_le_host_supported cp;
6390
Marcel Holtmann32226e42014-07-24 20:04:16 +02006391 cp.le = 0x01;
6392 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006393
6394 /* Check first if we already have the right
6395 * host state (host features set)
6396 */
6397 if (cp.le != lmp_host_le_capable(hdev) ||
6398 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006399 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6400 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006401 }
6402
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006403 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006404 /* Make sure the controller has a good default for
6405 * advertising data. This also applies to the case
6406 * where BR/EDR was toggled during the AUTO_OFF phase.
6407 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006408 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006409 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006410 update_scan_rsp_data(&req);
6411 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006412
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006413 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6414 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006415
6416 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006417 }
6418
Johan Hedberg70da6242013-03-15 17:06:51 -05006419 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6420 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006421 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6422 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006423
6424 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006425 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006426 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006427 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006428 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006429 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006430 }
6431
Johan Hedberg229ab392013-03-15 17:06:53 -05006432 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006433}
6434
Johan Hedberg744cf192011-11-08 20:40:14 +02006435int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006436{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006437 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006438 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006439 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006440
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006441 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6442 return 0;
6443
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006444 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006445 if (powered_update_hci(hdev) == 0)
6446 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006447
Johan Hedberg229ab392013-03-15 17:06:53 -05006448 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6449 &match);
6450 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006451 }
6452
Johan Hedberg229ab392013-03-15 17:06:53 -05006453 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006454
6455 /* If the power off is because of hdev unregistration let
6456 * use the appropriate INVALID_INDEX status. Otherwise use
6457 * NOT_POWERED. We cover both scenarios here since later in
6458 * mgmt_index_removed() any hci_conn callbacks will have already
6459 * been triggered, potentially causing misleading DISCONNECTED
6460 * status responses.
6461 */
6462 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6463 status = MGMT_STATUS_INVALID_INDEX;
6464 else
6465 status = MGMT_STATUS_NOT_POWERED;
6466
6467 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006468
6469 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6470 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6471 zero_cod, sizeof(zero_cod), NULL);
6472
6473new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006474 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006475
6476 if (match.sk)
6477 sock_put(match.sk);
6478
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006479 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006480}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006481
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006482void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006483{
6484 struct pending_cmd *cmd;
6485 u8 status;
6486
6487 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6488 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006489 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006490
6491 if (err == -ERFKILL)
6492 status = MGMT_STATUS_RFKILLED;
6493 else
6494 status = MGMT_STATUS_FAILED;
6495
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006496 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006497
6498 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006499}
6500
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006501void mgmt_discoverable_timeout(struct hci_dev *hdev)
6502{
6503 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006504
6505 hci_dev_lock(hdev);
6506
6507 /* When discoverable timeout triggers, then just make sure
6508 * the limited discoverable flag is cleared. Even in the case
6509 * of a timeout triggered from general discoverable, it is
6510 * safe to unconditionally clear the flag.
6511 */
6512 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006513 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006514
6515 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006516 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6517 u8 scan = SCAN_PAGE;
6518 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6519 sizeof(scan), &scan);
6520 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006521 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006522 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006523 hci_req_run(&req, NULL);
6524
6525 hdev->discov_timeout = 0;
6526
Johan Hedberg9a43e252013-10-20 19:00:07 +03006527 new_settings(hdev, NULL);
6528
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006529 hci_dev_unlock(hdev);
6530}
6531
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006532void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6533 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006534{
Johan Hedberg86742e12011-11-07 23:13:38 +02006535 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006536
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006537 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006538
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006539 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006540 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006541 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006542 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006543 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006544 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006545
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006546 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006547}
Johan Hedbergf7520542011-01-20 12:34:39 +02006548
Johan Hedbergd7b25452014-05-23 13:19:53 +03006549static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6550{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006551 switch (ltk->type) {
6552 case SMP_LTK:
6553 case SMP_LTK_SLAVE:
6554 if (ltk->authenticated)
6555 return MGMT_LTK_AUTHENTICATED;
6556 return MGMT_LTK_UNAUTHENTICATED;
6557 case SMP_LTK_P256:
6558 if (ltk->authenticated)
6559 return MGMT_LTK_P256_AUTH;
6560 return MGMT_LTK_P256_UNAUTH;
6561 case SMP_LTK_P256_DEBUG:
6562 return MGMT_LTK_P256_DEBUG;
6563 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006564
6565 return MGMT_LTK_UNAUTHENTICATED;
6566}
6567
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006568void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006569{
6570 struct mgmt_ev_new_long_term_key ev;
6571
6572 memset(&ev, 0, sizeof(ev));
6573
Marcel Holtmann5192d302014-02-19 17:11:58 -08006574 /* Devices using resolvable or non-resolvable random addresses
6575 * without providing an indentity resolving key don't require
6576 * to store long term keys. Their addresses will change the
6577 * next time around.
6578 *
6579 * Only when a remote device provides an identity address
6580 * make sure the long term key is stored. If the remote
6581 * identity is known, the long term keys are internally
6582 * mapped to the identity address. So allow static random
6583 * and public addresses here.
6584 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006585 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6586 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6587 ev.store_hint = 0x00;
6588 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006589 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006590
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006591 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006592 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006593 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006594 ev.key.enc_size = key->enc_size;
6595 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006596 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006597
Johan Hedberg2ceba532014-06-16 19:25:16 +03006598 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006599 ev.key.master = 1;
6600
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006601 memcpy(ev.key.val, key->val, sizeof(key->val));
6602
Marcel Holtmann083368f2013-10-15 14:26:29 -07006603 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006604}
6605
Johan Hedberg95fbac82014-02-19 15:18:31 +02006606void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6607{
6608 struct mgmt_ev_new_irk ev;
6609
6610 memset(&ev, 0, sizeof(ev));
6611
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006612 /* For identity resolving keys from devices that are already
6613 * using a public address or static random address, do not
6614 * ask for storing this key. The identity resolving key really
6615 * is only mandatory for devices using resovlable random
6616 * addresses.
6617 *
6618 * Storing all identity resolving keys has the downside that
6619 * they will be also loaded on next boot of they system. More
6620 * identity resolving keys, means more time during scanning is
6621 * needed to actually resolve these addresses.
6622 */
6623 if (bacmp(&irk->rpa, BDADDR_ANY))
6624 ev.store_hint = 0x01;
6625 else
6626 ev.store_hint = 0x00;
6627
Johan Hedberg95fbac82014-02-19 15:18:31 +02006628 bacpy(&ev.rpa, &irk->rpa);
6629 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6630 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6631 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6632
6633 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6634}
6635
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006636void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6637 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006638{
6639 struct mgmt_ev_new_csrk ev;
6640
6641 memset(&ev, 0, sizeof(ev));
6642
6643 /* Devices using resolvable or non-resolvable random addresses
6644 * without providing an indentity resolving key don't require
6645 * to store signature resolving keys. Their addresses will change
6646 * the next time around.
6647 *
6648 * Only when a remote device provides an identity address
6649 * make sure the signature resolving key is stored. So allow
6650 * static random and public addresses here.
6651 */
6652 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6653 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6654 ev.store_hint = 0x00;
6655 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006656 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006657
6658 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6659 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6660 ev.key.master = csrk->master;
6661 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6662
6663 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6664}
6665
Andre Guedesffb5a8272014-07-01 18:10:11 -03006666void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006667 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6668 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006669{
6670 struct mgmt_ev_new_conn_param ev;
6671
Johan Hedbergc103aea2014-07-02 17:37:34 +03006672 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6673 return;
6674
Andre Guedesffb5a8272014-07-01 18:10:11 -03006675 memset(&ev, 0, sizeof(ev));
6676 bacpy(&ev.addr.bdaddr, bdaddr);
6677 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006678 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006679 ev.min_interval = cpu_to_le16(min_interval);
6680 ev.max_interval = cpu_to_le16(max_interval);
6681 ev.latency = cpu_to_le16(latency);
6682 ev.timeout = cpu_to_le16(timeout);
6683
6684 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6685}
6686
Marcel Holtmann94933992013-10-15 10:26:39 -07006687static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6688 u8 data_len)
6689{
6690 eir[eir_len++] = sizeof(type) + data_len;
6691 eir[eir_len++] = type;
6692 memcpy(&eir[eir_len], data, data_len);
6693 eir_len += data_len;
6694
6695 return eir_len;
6696}
6697
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006698void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6699 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006700{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006701 char buf[512];
6702 struct mgmt_ev_device_connected *ev = (void *) buf;
6703 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006704
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006705 bacpy(&ev->addr.bdaddr, &conn->dst);
6706 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006707
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006708 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006709
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006710 /* We must ensure that the EIR Data fields are ordered and
6711 * unique. Keep it simple for now and avoid the problem by not
6712 * adding any BR/EDR data to the LE adv.
6713 */
6714 if (conn->le_adv_data_len > 0) {
6715 memcpy(&ev->eir[eir_len],
6716 conn->le_adv_data, conn->le_adv_data_len);
6717 eir_len = conn->le_adv_data_len;
6718 } else {
6719 if (name_len > 0)
6720 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6721 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006722
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006723 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006724 eir_len = eir_append_data(ev->eir, eir_len,
6725 EIR_CLASS_OF_DEV,
6726 conn->dev_class, 3);
6727 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006728
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006729 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006730
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006731 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6732 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006733}
6734
Johan Hedberg8962ee72011-01-20 12:40:27 +02006735static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6736{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006737 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006738
Johan Hedbergf5818c22014-12-05 13:36:02 +02006739 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006740
6741 *sk = cmd->sk;
6742 sock_hold(*sk);
6743
Johan Hedberga664b5b2011-02-19 12:06:02 -03006744 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006745}
6746
Johan Hedberg124f6e32012-02-09 13:50:12 +02006747static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006748{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006749 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006750 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006751
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006752 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6753
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006754 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006755 mgmt_pending_remove(cmd);
6756}
6757
Johan Hedberg84c61d92014-08-01 11:13:30 +03006758bool mgmt_powering_down(struct hci_dev *hdev)
6759{
6760 struct pending_cmd *cmd;
6761 struct mgmt_mode *cp;
6762
6763 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6764 if (!cmd)
6765 return false;
6766
6767 cp = cmd->param;
6768 if (!cp->val)
6769 return true;
6770
6771 return false;
6772}
6773
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006774void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006775 u8 link_type, u8 addr_type, u8 reason,
6776 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006777{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006778 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006779 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006780
Johan Hedberg84c61d92014-08-01 11:13:30 +03006781 /* The connection is still in hci_conn_hash so test for 1
6782 * instead of 0 to know if this is the last one.
6783 */
6784 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6785 cancel_delayed_work(&hdev->power_off);
6786 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006787 }
6788
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006789 if (!mgmt_connected)
6790 return;
6791
Andre Guedes57eb7762013-10-30 19:01:41 -03006792 if (link_type != ACL_LINK && link_type != LE_LINK)
6793 return;
6794
Johan Hedberg744cf192011-11-08 20:40:14 +02006795 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006796
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006797 bacpy(&ev.addr.bdaddr, bdaddr);
6798 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6799 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006800
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006801 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006802
6803 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006804 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006805
Johan Hedberg124f6e32012-02-09 13:50:12 +02006806 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006807 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006808}
6809
Marcel Holtmann78929242013-10-06 23:55:47 -07006810void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6811 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006812{
Andre Guedes3655bba2013-10-30 19:01:40 -03006813 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6814 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006815 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006816
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006817 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6818 hdev);
6819
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006820 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006821 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006822 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006823
Andre Guedes3655bba2013-10-30 19:01:40 -03006824 cp = cmd->param;
6825
6826 if (bacmp(bdaddr, &cp->addr.bdaddr))
6827 return;
6828
6829 if (cp->addr.type != bdaddr_type)
6830 return;
6831
Johan Hedbergf5818c22014-12-05 13:36:02 +02006832 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006833 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006834}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006835
Marcel Holtmann445608d2013-10-06 23:55:48 -07006836void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6837 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006838{
6839 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006840
Johan Hedberg84c61d92014-08-01 11:13:30 +03006841 /* The connection is still in hci_conn_hash so test for 1
6842 * instead of 0 to know if this is the last one.
6843 */
6844 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6845 cancel_delayed_work(&hdev->power_off);
6846 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006847 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006848
Johan Hedberg4c659c32011-11-07 23:13:39 +02006849 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006850 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006851 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006852
Marcel Holtmann445608d2013-10-06 23:55:48 -07006853 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006854}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006855
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006856void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006857{
6858 struct mgmt_ev_pin_code_request ev;
6859
Johan Hedbergd8457692012-02-17 14:24:57 +02006860 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006861 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006862 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006863
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006864 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006865}
6866
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006867void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6868 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006869{
6870 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006871
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006872 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006873 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006874 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006875
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006876 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006877 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006878}
6879
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006880void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6881 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006882{
6883 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006884
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006885 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006886 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006887 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006888
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006889 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006890 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006891}
Johan Hedberga5c29682011-02-19 12:05:57 -03006892
Johan Hedberg744cf192011-11-08 20:40:14 +02006893int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006894 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006895 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006896{
6897 struct mgmt_ev_user_confirm_request ev;
6898
Johan Hedberg744cf192011-11-08 20:40:14 +02006899 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006900
Johan Hedberg272d90d2012-02-09 15:26:12 +02006901 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006902 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006903 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006904 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006905
Johan Hedberg744cf192011-11-08 20:40:14 +02006906 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006907 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006908}
6909
Johan Hedberg272d90d2012-02-09 15:26:12 +02006910int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006911 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006912{
6913 struct mgmt_ev_user_passkey_request ev;
6914
6915 BT_DBG("%s", hdev->name);
6916
Johan Hedberg272d90d2012-02-09 15:26:12 +02006917 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006918 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006919
6920 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006921 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006922}
6923
Brian Gix0df4c182011-11-16 13:53:13 -08006924static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006925 u8 link_type, u8 addr_type, u8 status,
6926 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006927{
6928 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006929
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006930 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006931 if (!cmd)
6932 return -ENOENT;
6933
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006934 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006935 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006936
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006937 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006938}
6939
Johan Hedberg744cf192011-11-08 20:40:14 +02006940int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006941 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006942{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006943 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006944 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006945}
6946
Johan Hedberg272d90d2012-02-09 15:26:12 +02006947int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006948 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006949{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006950 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006951 status,
6952 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006953}
Johan Hedberg2a611692011-02-19 12:06:00 -03006954
Brian Gix604086b2011-11-23 08:28:33 -08006955int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006956 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006957{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006958 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006959 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006960}
6961
Johan Hedberg272d90d2012-02-09 15:26:12 +02006962int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006963 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006964{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006965 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006966 status,
6967 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006968}
6969
Johan Hedberg92a25252012-09-06 18:39:26 +03006970int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6971 u8 link_type, u8 addr_type, u32 passkey,
6972 u8 entered)
6973{
6974 struct mgmt_ev_passkey_notify ev;
6975
6976 BT_DBG("%s", hdev->name);
6977
6978 bacpy(&ev.addr.bdaddr, bdaddr);
6979 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6980 ev.passkey = __cpu_to_le32(passkey);
6981 ev.entered = entered;
6982
6983 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6984}
6985
Johan Hedberge1e930f2014-09-08 17:09:49 -07006986void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006987{
6988 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006989 struct pending_cmd *cmd;
6990 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006991
Johan Hedberge1e930f2014-09-08 17:09:49 -07006992 bacpy(&ev.addr.bdaddr, &conn->dst);
6993 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6994 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006995
Johan Hedberge1e930f2014-09-08 17:09:49 -07006996 cmd = find_pairing(conn);
6997
6998 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6999 cmd ? cmd->sk : NULL);
7000
Johan Hedberga511b352014-12-11 21:45:45 +02007001 if (cmd) {
7002 cmd->cmd_complete(cmd, status);
7003 mgmt_pending_remove(cmd);
7004 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007005}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007006
Marcel Holtmann464996a2013-10-15 14:26:24 -07007007void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007008{
7009 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007010 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007011
7012 if (status) {
7013 u8 mgmt_err = mgmt_status(status);
7014 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007015 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007016 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007017 }
7018
Marcel Holtmann464996a2013-10-15 14:26:24 -07007019 if (test_bit(HCI_AUTH, &hdev->flags))
7020 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7021 &hdev->dev_flags);
7022 else
7023 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7024 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007025
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007026 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007027 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007028
Johan Hedberg47990ea2012-02-22 11:58:37 +02007029 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007030 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007031
7032 if (match.sk)
7033 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007034}
7035
Johan Hedberg890ea892013-03-15 17:06:52 -05007036static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007037{
Johan Hedberg890ea892013-03-15 17:06:52 -05007038 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007039 struct hci_cp_write_eir cp;
7040
Johan Hedberg976eb202012-10-24 21:12:01 +03007041 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007042 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007043
Johan Hedbergc80da272012-02-22 15:38:48 +02007044 memset(hdev->eir, 0, sizeof(hdev->eir));
7045
Johan Hedbergcacaf522012-02-21 00:52:42 +02007046 memset(&cp, 0, sizeof(cp));
7047
Johan Hedberg890ea892013-03-15 17:06:52 -05007048 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007049}
7050
Marcel Holtmann3e248562013-10-15 14:26:25 -07007051void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007052{
7053 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007054 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007055 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007056
7057 if (status) {
7058 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007059
7060 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007061 &hdev->dev_flags)) {
7062 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007063 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007064 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007065
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007066 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7067 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007068 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007069 }
7070
7071 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007072 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007073 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007074 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7075 if (!changed)
7076 changed = test_and_clear_bit(HCI_HS_ENABLED,
7077 &hdev->dev_flags);
7078 else
7079 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007080 }
7081
7082 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7083
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007084 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007085 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007086
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007087 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007088 sock_put(match.sk);
7089
Johan Hedberg890ea892013-03-15 17:06:52 -05007090 hci_req_init(&req, hdev);
7091
Johan Hedberg37699722014-06-24 14:00:27 +03007092 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
7093 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
7094 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7095 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007096 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007097 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007098 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007099 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007100
7101 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007102}
7103
Johan Hedberg92da6092013-03-15 17:06:55 -05007104static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007105{
7106 struct cmd_lookup *match = data;
7107
Johan Hedberg90e70452012-02-23 23:09:40 +02007108 if (match->sk == NULL) {
7109 match->sk = cmd->sk;
7110 sock_hold(match->sk);
7111 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007112}
7113
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007114void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7115 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007116{
Johan Hedberg90e70452012-02-23 23:09:40 +02007117 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007118
Johan Hedberg92da6092013-03-15 17:06:55 -05007119 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7120 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7121 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007122
7123 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007124 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7125 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007126
7127 if (match.sk)
7128 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007129}
7130
Marcel Holtmann7667da32013-10-15 14:26:27 -07007131void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007132{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007133 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05007134 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007135
Johan Hedberg13928972013-03-15 17:07:00 -05007136 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007137 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007138
7139 memset(&ev, 0, sizeof(ev));
7140 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007141 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007142
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007143 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007144 if (!cmd) {
7145 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007146
Johan Hedberg13928972013-03-15 17:07:00 -05007147 /* If this is a HCI command related to powering on the
7148 * HCI dev don't send any mgmt signals.
7149 */
7150 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007151 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007152 }
7153
Marcel Holtmann7667da32013-10-15 14:26:27 -07007154 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7155 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007156}
Szymon Jancc35938b2011-03-22 13:12:21 +01007157
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007158void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007159 u8 *rand192, u8 *hash256, u8 *rand256,
7160 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007161{
7162 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007163
Johan Hedberg744cf192011-11-08 20:40:14 +02007164 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007165
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007166 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007167 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007168 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007169
7170 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007171 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7172 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007173 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007174 struct mgmt_rp_read_local_oob_data rp;
7175 size_t rp_size = sizeof(rp);
7176
7177 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7178 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7179
Johan Hedberg710f11c2014-05-26 11:21:22 +03007180 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007181 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007182 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007183 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007184 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007185 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007186
7187 cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7188 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007189 }
7190
7191 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007192}
Johan Hedberge17acd42011-03-30 23:57:16 +03007193
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007194static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7195{
7196 int i;
7197
7198 for (i = 0; i < uuid_count; i++) {
7199 if (!memcmp(uuid, uuids[i], 16))
7200 return true;
7201 }
7202
7203 return false;
7204}
7205
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007206static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7207{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007208 u16 parsed = 0;
7209
7210 while (parsed < eir_len) {
7211 u8 field_len = eir[0];
7212 u8 uuid[16];
7213 int i;
7214
7215 if (field_len == 0)
7216 break;
7217
7218 if (eir_len - parsed < field_len + 1)
7219 break;
7220
7221 switch (eir[1]) {
7222 case EIR_UUID16_ALL:
7223 case EIR_UUID16_SOME:
7224 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007225 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007226 uuid[13] = eir[i + 3];
7227 uuid[12] = eir[i + 2];
7228 if (has_uuid(uuid, uuid_count, uuids))
7229 return true;
7230 }
7231 break;
7232 case EIR_UUID32_ALL:
7233 case EIR_UUID32_SOME:
7234 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007235 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007236 uuid[15] = eir[i + 5];
7237 uuid[14] = eir[i + 4];
7238 uuid[13] = eir[i + 3];
7239 uuid[12] = eir[i + 2];
7240 if (has_uuid(uuid, uuid_count, uuids))
7241 return true;
7242 }
7243 break;
7244 case EIR_UUID128_ALL:
7245 case EIR_UUID128_SOME:
7246 for (i = 0; i + 17 <= field_len; i += 16) {
7247 memcpy(uuid, eir + i + 2, 16);
7248 if (has_uuid(uuid, uuid_count, uuids))
7249 return true;
7250 }
7251 break;
7252 }
7253
7254 parsed += field_len + 1;
7255 eir += field_len + 1;
7256 }
7257
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007258 return false;
7259}
7260
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007261static void restart_le_scan(struct hci_dev *hdev)
7262{
7263 /* If controller is not scanning we are done. */
7264 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7265 return;
7266
7267 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7268 hdev->discovery.scan_start +
7269 hdev->discovery.scan_duration))
7270 return;
7271
7272 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7273 DISCOV_LE_RESTART_DELAY);
7274}
7275
Marcel Holtmann901801b2013-10-06 23:55:51 -07007276void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007277 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7278 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007279{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007280 char buf[512];
7281 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007282 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007283 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007284
Johan Hedberg75ce2082014-07-02 22:42:01 +03007285 /* Don't send events for a non-kernel initiated discovery. With
7286 * LE one exception is if we have pend_le_reports > 0 in which
7287 * case we're doing passive scanning and want these events.
7288 */
7289 if (!hci_discovery_active(hdev)) {
7290 if (link_type == ACL_LINK)
7291 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007292 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007293 return;
7294 }
Andre Guedes12602d02013-04-30 15:29:40 -03007295
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007296 /* When using service discovery with a RSSI threshold, then check
7297 * if such a RSSI threshold is specified. If a RSSI threshold has
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007298 * been specified, and HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set,
7299 * then all results with a RSSI smaller than the RSSI threshold will be
7300 * dropped. If the quirk is set, let it through for further processing,
7301 * as we might need to restart the scan.
Marcel Holtmannefb25132014-12-05 13:03:34 +01007302 *
7303 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7304 * the results are also dropped.
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007305 */
7306 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007307 (rssi == HCI_RSSI_INVALID ||
7308 (rssi < hdev->discovery.rssi &&
7309 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007310 return;
7311
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007312 /* Make sure that the buffer is big enough. The 5 extra bytes
7313 * are for the potential CoD field.
7314 */
7315 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007316 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007317
Johan Hedberg1dc06092012-01-15 21:01:23 +02007318 memset(buf, 0, sizeof(buf));
7319
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007320 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7321 * RSSI value was reported as 0 when not available. This behavior
7322 * is kept when using device discovery. This is required for full
7323 * backwards compatibility with the API.
7324 *
7325 * However when using service discovery, the value 127 will be
7326 * returned when the RSSI is not available.
7327 */
Szymon Janc91200e92015-01-22 16:57:05 +01007328 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7329 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007330 rssi = 0;
7331
Johan Hedberg841c5642014-07-07 12:45:54 +03007332 bacpy(&ev->addr.bdaddr, bdaddr);
7333 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007334 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007335 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007336
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007337 if (eir_len > 0) {
7338 /* When using service discovery and a list of UUID is
7339 * provided, results with no matching UUID should be
7340 * dropped. In case there is a match the result is
7341 * kept and checking possible scan response data
7342 * will be skipped.
7343 */
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007344 if (hdev->discovery.uuid_count > 0) {
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007345 match = eir_has_uuids(eir, eir_len,
7346 hdev->discovery.uuid_count,
7347 hdev->discovery.uuids);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007348 /* If duplicate filtering does not report RSSI changes,
7349 * then restart scanning to ensure updated result with
7350 * updated RSSI values.
7351 */
7352 if (match && test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
7353 &hdev->quirks))
7354 restart_le_scan(hdev);
7355 } else {
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007356 match = true;
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007357 }
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007358
7359 if (!match && !scan_rsp_len)
7360 return;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007361
7362 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007363 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007364 } else {
7365 /* When using service discovery and a list of UUID is
7366 * provided, results with empty EIR or advertising data
7367 * should be dropped since they do not match any UUID.
7368 */
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007369 if (hdev->discovery.uuid_count > 0 && !scan_rsp_len)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007370 return;
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007371
7372 match = false;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007373 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007374
Johan Hedberg1dc06092012-01-15 21:01:23 +02007375 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7376 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007377 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007378
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007379 if (scan_rsp_len > 0) {
7380 /* When using service discovery and a list of UUID is
7381 * provided, results with no matching UUID should be
7382 * dropped if there is no previous match from the
7383 * advertising data.
7384 */
7385 if (hdev->discovery.uuid_count > 0) {
7386 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7387 hdev->discovery.uuid_count,
7388 hdev->discovery.uuids))
7389 return;
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007390
7391 /* If duplicate filtering does not report RSSI changes,
7392 * then restart scanning to ensure updated result with
7393 * updated RSSI values.
7394 */
7395 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
7396 &hdev->quirks))
7397 restart_le_scan(hdev);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007398 }
7399
7400 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007401 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007402 } else {
7403 /* When using service discovery and a list of UUID is
7404 * provided, results with empty scan response and no
7405 * previous matched advertising data should be dropped.
7406 */
7407 if (hdev->discovery.uuid_count > 0 && !match)
7408 return;
7409 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007410
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007411 /* Validate the reported RSSI value against the RSSI threshold once more
7412 * incase HCI_QUIRK_STRICT_DUPLICATE_FILTER forced a restart of LE
7413 * scanning.
7414 */
7415 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7416 rssi < hdev->discovery.rssi)
7417 return;
7418
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007419 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7420 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007421
Marcel Holtmann901801b2013-10-06 23:55:51 -07007422 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007423}
Johan Hedberga88a9652011-03-30 13:18:12 +03007424
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007425void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7426 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007427{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007428 struct mgmt_ev_device_found *ev;
7429 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7430 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007431
Johan Hedbergb644ba32012-01-17 21:48:47 +02007432 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007433
Johan Hedbergb644ba32012-01-17 21:48:47 +02007434 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007435
Johan Hedbergb644ba32012-01-17 21:48:47 +02007436 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007437 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007438 ev->rssi = rssi;
7439
7440 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007441 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007442
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007443 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007444
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007445 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007446}
Johan Hedberg314b2382011-04-27 10:29:57 -04007447
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007448void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007449{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007450 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007451
Andre Guedes343fb142011-11-22 17:14:19 -03007452 BT_DBG("%s discovering %u", hdev->name, discovering);
7453
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007454 memset(&ev, 0, sizeof(ev));
7455 ev.type = hdev->discovery.type;
7456 ev.discovering = discovering;
7457
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007458 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007459}
Antti Julku5e762442011-08-25 16:48:02 +03007460
Marcel Holtmann1904a852015-01-11 13:50:44 -08007461static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007462{
7463 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007464}
7465
7466void mgmt_reenable_advertising(struct hci_dev *hdev)
7467{
7468 struct hci_request req;
7469
Marcel Holtmann5976e602013-10-06 04:08:14 -07007470 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7471 return;
7472
7473 hci_req_init(&req, hdev);
7474 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007475 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007476}