blob: 0fc3d6914ef0ecce1c75dcd39f28fd2369b0bd74 [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
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann854bda12014-12-03 19:52:43 +010038#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010096 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020097};
98
99static const u16 mgmt_events[] = {
100 MGMT_EV_CONTROLLER_ERROR,
101 MGMT_EV_INDEX_ADDED,
102 MGMT_EV_INDEX_REMOVED,
103 MGMT_EV_NEW_SETTINGS,
104 MGMT_EV_CLASS_OF_DEV_CHANGED,
105 MGMT_EV_LOCAL_NAME_CHANGED,
106 MGMT_EV_NEW_LINK_KEY,
107 MGMT_EV_NEW_LONG_TERM_KEY,
108 MGMT_EV_DEVICE_CONNECTED,
109 MGMT_EV_DEVICE_DISCONNECTED,
110 MGMT_EV_CONNECT_FAILED,
111 MGMT_EV_PIN_CODE_REQUEST,
112 MGMT_EV_USER_CONFIRM_REQUEST,
113 MGMT_EV_USER_PASSKEY_REQUEST,
114 MGMT_EV_AUTH_FAILED,
115 MGMT_EV_DEVICE_FOUND,
116 MGMT_EV_DISCOVERING,
117 MGMT_EV_DEVICE_BLOCKED,
118 MGMT_EV_DEVICE_UNBLOCKED,
119 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300120 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800121 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700122 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200123 MGMT_EV_DEVICE_ADDED,
124 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300125 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200126 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200127 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200128 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200129};
130
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800131#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200138 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300140 void *user_data;
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +0200141 void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300556 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300580 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200581 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300582 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200583
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200584 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
585 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200586 settings |= MGMT_SETTING_CONFIGURATION;
587
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200588 return settings;
589}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200590
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200591static u32 get_current_settings(struct hci_dev *hdev)
592{
593 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200594
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200595 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100596 settings |= MGMT_SETTING_POWERED;
597
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200598 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200599 settings |= MGMT_SETTING_CONNECTABLE;
600
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500601 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
602 settings |= MGMT_SETTING_FAST_CONNECTABLE;
603
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200604 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605 settings |= MGMT_SETTING_DISCOVERABLE;
606
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300607 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300608 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609
Johan Hedberg56f87902013-10-02 13:43:13 +0300610 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200611 settings |= MGMT_SETTING_BREDR;
612
Johan Hedberg06199cf2012-02-22 16:37:11 +0200613 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200615
Johan Hedberg47990ea2012-02-22 11:58:37 +0200616 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200618
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200619 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200620 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200621
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200622 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
623 settings |= MGMT_SETTING_HS;
624
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200625 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300626 settings |= MGMT_SETTING_ADVERTISING;
627
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800628 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
629 settings |= MGMT_SETTING_SECURE_CONN;
630
Johan Hedberg0663b292014-06-24 13:15:50 +0300631 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800632 settings |= MGMT_SETTING_DEBUG_KEYS;
633
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
635 settings |= MGMT_SETTING_PRIVACY;
636
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200637 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200638}
639
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300640#define PNP_INFO_SVCLASS_ID 0x1200
641
Johan Hedberg213202e2013-01-27 00:31:33 +0200642static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
643{
644 u8 *ptr = data, *uuids_start = NULL;
645 struct bt_uuid *uuid;
646
647 if (len < 4)
648 return ptr;
649
650 list_for_each_entry(uuid, &hdev->uuids, list) {
651 u16 uuid16;
652
653 if (uuid->size != 16)
654 continue;
655
656 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
657 if (uuid16 < 0x1100)
658 continue;
659
660 if (uuid16 == PNP_INFO_SVCLASS_ID)
661 continue;
662
663 if (!uuids_start) {
664 uuids_start = ptr;
665 uuids_start[0] = 1;
666 uuids_start[1] = EIR_UUID16_ALL;
667 ptr += 2;
668 }
669
670 /* Stop if not enough space to put next UUID */
671 if ((ptr - data) + sizeof(u16) > len) {
672 uuids_start[1] = EIR_UUID16_SOME;
673 break;
674 }
675
676 *ptr++ = (uuid16 & 0x00ff);
677 *ptr++ = (uuid16 & 0xff00) >> 8;
678 uuids_start[0] += sizeof(uuid16);
679 }
680
681 return ptr;
682}
683
Johan Hedbergcdf19632013-01-27 00:31:34 +0200684static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
685{
686 u8 *ptr = data, *uuids_start = NULL;
687 struct bt_uuid *uuid;
688
689 if (len < 6)
690 return ptr;
691
692 list_for_each_entry(uuid, &hdev->uuids, list) {
693 if (uuid->size != 32)
694 continue;
695
696 if (!uuids_start) {
697 uuids_start = ptr;
698 uuids_start[0] = 1;
699 uuids_start[1] = EIR_UUID32_ALL;
700 ptr += 2;
701 }
702
703 /* Stop if not enough space to put next UUID */
704 if ((ptr - data) + sizeof(u32) > len) {
705 uuids_start[1] = EIR_UUID32_SOME;
706 break;
707 }
708
709 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
710 ptr += sizeof(u32);
711 uuids_start[0] += sizeof(u32);
712 }
713
714 return ptr;
715}
716
Johan Hedbergc00d5752013-01-27 00:31:35 +0200717static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
718{
719 u8 *ptr = data, *uuids_start = NULL;
720 struct bt_uuid *uuid;
721
722 if (len < 18)
723 return ptr;
724
725 list_for_each_entry(uuid, &hdev->uuids, list) {
726 if (uuid->size != 128)
727 continue;
728
729 if (!uuids_start) {
730 uuids_start = ptr;
731 uuids_start[0] = 1;
732 uuids_start[1] = EIR_UUID128_ALL;
733 ptr += 2;
734 }
735
736 /* Stop if not enough space to put next UUID */
737 if ((ptr - data) + 16 > len) {
738 uuids_start[1] = EIR_UUID128_SOME;
739 break;
740 }
741
742 memcpy(ptr, uuid->uuid, 16);
743 ptr += 16;
744 uuids_start[0] += 16;
745 }
746
747 return ptr;
748}
749
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300750static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
751{
752 struct pending_cmd *cmd;
753
754 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
755 if (cmd->opcode == opcode)
756 return cmd;
757 }
758
759 return NULL;
760}
761
Johan Hedberg95868422014-06-28 17:54:07 +0300762static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
763 struct hci_dev *hdev,
764 const void *data)
765{
766 struct pending_cmd *cmd;
767
768 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
769 if (cmd->user_data != data)
770 continue;
771 if (cmd->opcode == opcode)
772 return cmd;
773 }
774
775 return NULL;
776}
777
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700778static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
779{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700780 u8 ad_len = 0;
781 size_t name_len;
782
783 name_len = strlen(hdev->dev_name);
784 if (name_len > 0) {
785 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
786
787 if (name_len > max_len) {
788 name_len = max_len;
789 ptr[1] = EIR_NAME_SHORT;
790 } else
791 ptr[1] = EIR_NAME_COMPLETE;
792
793 ptr[0] = name_len + 1;
794
795 memcpy(ptr + 2, hdev->dev_name, name_len);
796
797 ad_len += (name_len + 2);
798 ptr += (name_len + 2);
799 }
800
801 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700802}
803
804static void update_scan_rsp_data(struct hci_request *req)
805{
806 struct hci_dev *hdev = req->hdev;
807 struct hci_cp_le_set_scan_rsp_data cp;
808 u8 len;
809
Johan Hedberg7751ef12013-10-19 23:38:15 +0300810 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811 return;
812
813 memset(&cp, 0, sizeof(cp));
814
815 len = create_scan_rsp_data(hdev, cp.data);
816
Johan Hedbergeb438b52013-10-16 15:31:07 +0300817 if (hdev->scan_rsp_data_len == len &&
818 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700819 return;
820
Johan Hedbergeb438b52013-10-16 15:31:07 +0300821 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
822 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700823
824 cp.length = len;
825
826 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
827}
828
Johan Hedberg9a43e252013-10-20 19:00:07 +0300829static u8 get_adv_discov_flags(struct hci_dev *hdev)
830{
831 struct pending_cmd *cmd;
832
833 /* If there's a pending mgmt command the flags will not yet have
834 * their final values, so check for this first.
835 */
836 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
837 if (cmd) {
838 struct mgmt_mode *cp = cmd->param;
839 if (cp->val == 0x01)
840 return LE_AD_GENERAL;
841 else if (cp->val == 0x02)
842 return LE_AD_LIMITED;
843 } else {
844 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
845 return LE_AD_LIMITED;
846 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
847 return LE_AD_GENERAL;
848 }
849
850 return 0;
851}
852
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700853static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854{
855 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856
Johan Hedberg9a43e252013-10-20 19:00:07 +0300857 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858
Johan Hedberge8340042014-01-30 11:16:50 -0800859 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700861
862 if (flags) {
863 BT_DBG("adv flags 0x%02x", flags);
864
865 ptr[0] = 2;
866 ptr[1] = EIR_FLAGS;
867 ptr[2] = flags;
868
869 ad_len += 3;
870 ptr += 3;
871 }
872
873 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
874 ptr[0] = 2;
875 ptr[1] = EIR_TX_POWER;
876 ptr[2] = (u8) hdev->adv_tx_power;
877
878 ad_len += 3;
879 ptr += 3;
880 }
881
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882 return ad_len;
883}
884
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700885static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700886{
887 struct hci_dev *hdev = req->hdev;
888 struct hci_cp_le_set_adv_data cp;
889 u8 len;
890
Johan Hedberg10994ce2013-10-19 23:38:16 +0300891 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700892 return;
893
894 memset(&cp, 0, sizeof(cp));
895
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700896 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700897
898 if (hdev->adv_data_len == len &&
899 memcmp(cp.data, hdev->adv_data, len) == 0)
900 return;
901
902 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
903 hdev->adv_data_len = len;
904
905 cp.length = len;
906
907 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
908}
909
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300910int mgmt_update_adv_data(struct hci_dev *hdev)
911{
912 struct hci_request req;
913
914 hci_req_init(&req, hdev);
915 update_adv_data(&req);
916
917 return hci_req_run(&req, NULL);
918}
919
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300920static void create_eir(struct hci_dev *hdev, u8 *data)
921{
922 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300923 size_t name_len;
924
925 name_len = strlen(hdev->dev_name);
926
927 if (name_len > 0) {
928 /* EIR Data type */
929 if (name_len > 48) {
930 name_len = 48;
931 ptr[1] = EIR_NAME_SHORT;
932 } else
933 ptr[1] = EIR_NAME_COMPLETE;
934
935 /* EIR Data length */
936 ptr[0] = name_len + 1;
937
938 memcpy(ptr + 2, hdev->dev_name, name_len);
939
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300940 ptr += (name_len + 2);
941 }
942
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100943 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700944 ptr[0] = 2;
945 ptr[1] = EIR_TX_POWER;
946 ptr[2] = (u8) hdev->inq_tx_power;
947
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700948 ptr += 3;
949 }
950
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700951 if (hdev->devid_source > 0) {
952 ptr[0] = 9;
953 ptr[1] = EIR_DEVICE_ID;
954
955 put_unaligned_le16(hdev->devid_source, ptr + 2);
956 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
957 put_unaligned_le16(hdev->devid_product, ptr + 6);
958 put_unaligned_le16(hdev->devid_version, ptr + 8);
959
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700960 ptr += 10;
961 }
962
Johan Hedberg213202e2013-01-27 00:31:33 +0200963 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200964 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200965 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300966}
967
Johan Hedberg890ea892013-03-15 17:06:52 -0500968static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300969{
Johan Hedberg890ea892013-03-15 17:06:52 -0500970 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300971 struct hci_cp_write_eir cp;
972
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200973 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500974 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200975
Johan Hedberg976eb202012-10-24 21:12:01 +0300976 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500977 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300978
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200979 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200982 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984
985 memset(&cp, 0, sizeof(cp));
986
987 create_eir(hdev, cp.data);
988
989 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500990 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300991
992 memcpy(hdev->eir, cp.data, sizeof(cp.data));
993
Johan Hedberg890ea892013-03-15 17:06:52 -0500994 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300995}
996
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200997static u8 get_service_classes(struct hci_dev *hdev)
998{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300999 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 val = 0;
1001
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001002 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001004
1005 return val;
1006}
1007
Johan Hedberg890ea892013-03-15 17:06:52 -05001008static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001009{
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001011 u8 cod[3];
1012
1013 BT_DBG("%s", hdev->name);
1014
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001015 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001017
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001018 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1019 return;
1020
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001021 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001022 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001023
1024 cod[0] = hdev->minor_class;
1025 cod[1] = hdev->major_class;
1026 cod[2] = get_service_classes(hdev);
1027
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001028 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1029 cod[1] |= 0x20;
1030
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001031 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001032 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033
Johan Hedberg890ea892013-03-15 17:06:52 -05001034 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001035}
1036
Johan Hedberga4858cb2014-02-25 19:56:31 +02001037static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001038{
1039 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040
1041 /* If there's a pending mgmt command the flag will not yet have
1042 * it's final value, so check for this first.
1043 */
1044 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1045 if (cmd) {
1046 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048 }
1049
Johan Hedberga4858cb2014-02-25 19:56:31 +02001050 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001051}
1052
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001053static void disable_advertising(struct hci_request *req)
1054{
1055 u8 enable = 0x00;
1056
1057 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1058}
1059
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001060static void enable_advertising(struct hci_request *req)
1061{
1062 struct hci_dev *hdev = req->hdev;
1063 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001064 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001065 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001066
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001067 if (hci_conn_num(hdev, LE_LINK) > 0)
1068 return;
1069
1070 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1071 disable_advertising(req);
1072
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001073 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001074 * hci_update_random_address knows that it's safe to go ahead
1075 * and write a new random address. The flag will be set back on
1076 * as soon as the SET_ADV_ENABLE HCI command completes.
1077 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001078 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001079
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001081
Johan Hedberga4858cb2014-02-25 19:56:31 +02001082 /* Set require_privacy to true only when non-connectable
1083 * advertising is used. In that case it is fine to use a
1084 * non-resolvable private address.
1085 */
1086 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001087 return;
1088
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001089 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001090 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1091 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001092 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001093 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001094 cp.channel_map = hdev->le_adv_channel_map;
1095
1096 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1097
1098 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1099}
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101static void service_cache_off(struct work_struct *work)
1102{
1103 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001104 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001105 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001106
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001107 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001108 return;
1109
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 hci_req_init(&req, hdev);
1111
Johan Hedberg7d785252011-12-15 00:47:39 +02001112 hci_dev_lock(hdev);
1113
Johan Hedberg890ea892013-03-15 17:06:52 -05001114 update_eir(&req);
1115 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001116
1117 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001118
1119 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001120}
1121
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122static void rpa_expired(struct work_struct *work)
1123{
1124 struct hci_dev *hdev = container_of(work, struct hci_dev,
1125 rpa_expired.work);
1126 struct hci_request req;
1127
1128 BT_DBG("");
1129
1130 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1131
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001132 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001133 return;
1134
1135 /* The generation of a new RPA and programming it into the
1136 * controller happens in the enable_advertising() function.
1137 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001140 hci_req_run(&req, NULL);
1141}
1142
Johan Hedberg6a919082012-02-28 06:17:26 +02001143static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001144{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001145 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001146 return;
1147
Johan Hedberg4f87da82012-03-02 19:55:56 +02001148 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001149 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001150
Johan Hedberg4f87da82012-03-02 19:55:56 +02001151 /* Non-mgmt controlled devices get this bit set
1152 * implicitly so that pairing works for them, however
1153 * for mgmt we require user-space to explicitly enable
1154 * it
1155 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001156 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001157}
1158
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001159static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001160 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001161{
1162 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001164 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001165
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001166 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001167
Johan Hedberg03811012010-12-08 00:21:06 +02001168 memset(&rp, 0, sizeof(rp));
1169
Johan Hedberg03811012010-12-08 00:21:06 +02001170 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001171
1172 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001173 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001174
1175 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1176 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1177
1178 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001179
1180 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001181 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001183 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001184
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001185 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001187}
1188
1189static void mgmt_pending_free(struct pending_cmd *cmd)
1190{
1191 sock_put(cmd->sk);
1192 kfree(cmd->param);
1193 kfree(cmd);
1194}
1195
1196static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001197 struct hci_dev *hdev, void *data,
1198 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001199{
1200 struct pending_cmd *cmd;
1201
Johan Hedbergfca20012014-06-28 17:54:05 +03001202 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 if (!cmd)
1204 return NULL;
1205
1206 cmd->opcode = opcode;
1207 cmd->index = hdev->id;
1208
Johan Hedberg323b0b82014-12-05 13:36:01 +02001209 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001210 if (!cmd->param) {
1211 kfree(cmd);
1212 return NULL;
1213 }
1214
Johan Hedberg323b0b82014-12-05 13:36:01 +02001215 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001475static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 if (cmd->cmd_complete) {
1478 u8 *status = data;
1479
1480 cmd->cmd_complete(cmd, *status);
1481 mgmt_pending_remove(cmd);
1482
1483 return;
1484 }
1485
1486 cmd_status_rsp(cmd, data);
1487}
1488
Johan Hedbergf5818c22014-12-05 13:36:02 +02001489static void generic_cmd_complete(struct pending_cmd *cmd, u8 status)
1490{
1491 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1492 cmd->param_len);
1493}
1494
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001495static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
1496{
1497 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1498 sizeof(struct mgmt_addr_info));
1499}
1500
Johan Hedberge6fe7982013-10-02 15:45:22 +03001501static u8 mgmt_bredr_support(struct hci_dev *hdev)
1502{
1503 if (!lmp_bredr_capable(hdev))
1504 return MGMT_STATUS_NOT_SUPPORTED;
1505 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1506 return MGMT_STATUS_REJECTED;
1507 else
1508 return MGMT_STATUS_SUCCESS;
1509}
1510
1511static u8 mgmt_le_support(struct hci_dev *hdev)
1512{
1513 if (!lmp_le_capable(hdev))
1514 return MGMT_STATUS_NOT_SUPPORTED;
1515 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1516 return MGMT_STATUS_REJECTED;
1517 else
1518 return MGMT_STATUS_SUCCESS;
1519}
1520
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1522{
1523 struct pending_cmd *cmd;
1524 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001525 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526 bool changed;
1527
1528 BT_DBG("status 0x%02x", status);
1529
1530 hci_dev_lock(hdev);
1531
1532 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1533 if (!cmd)
1534 goto unlock;
1535
1536 if (status) {
1537 u8 mgmt_err = mgmt_status(status);
1538 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001539 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001540 goto remove_cmd;
1541 }
1542
1543 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001544 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1546 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001547
1548 if (hdev->discov_timeout > 0) {
1549 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1550 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1551 to);
1552 }
1553 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001554 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1555 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001556 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557
1558 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1559
1560 if (changed)
1561 new_settings(hdev, cmd->sk);
1562
Marcel Holtmann970ba522013-10-15 06:33:57 -07001563 /* When the discoverable mode gets changed, make sure
1564 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001565 * bit correctly set. Also update page scan based on whitelist
1566 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001567 */
1568 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001569 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001570 update_class(&req);
1571 hci_req_run(&req, NULL);
1572
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001573remove_cmd:
1574 mgmt_pending_remove(cmd);
1575
1576unlock:
1577 hci_dev_unlock(hdev);
1578}
1579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001583 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001584 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001585 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001587 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001588 int err;
1589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001590 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001591
Johan Hedberg9a43e252013-10-20 19:00:07 +03001592 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1593 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001594 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001595 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001596
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001597 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001598 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1599 MGMT_STATUS_INVALID_PARAMS);
1600
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001601 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001602
1603 /* Disabling discoverable requires that no timeout is set,
1604 * and enabling limited discoverable requires a timeout.
1605 */
1606 if ((cp->val == 0x00 && timeout > 0) ||
1607 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001608 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001609 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001611 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001612
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001613 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001614 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001615 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001620 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001621 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001622 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001623 goto failed;
1624 }
1625
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001626 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001628 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001629 goto failed;
1630 }
1631
1632 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 bool changed = false;
1634
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001635 /* Setting limited discoverable when powered off is
1636 * not a valid operation since it requires a timeout
1637 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1638 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001639 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1640 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1641 changed = true;
1642 }
1643
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001644 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001645 if (err < 0)
1646 goto failed;
1647
1648 if (changed)
1649 err = new_settings(hdev, sk);
1650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001651 goto failed;
1652 }
1653
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 /* If the current mode is the same, then just update the timeout
1655 * value with the new value. And if only the timeout gets updated,
1656 * then no need for any HCI transactions.
1657 */
1658 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1659 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1660 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001661 cancel_delayed_work(&hdev->discov_off);
1662 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001663
Marcel Holtmann36261542013-10-15 08:28:51 -07001664 if (cp->val && hdev->discov_timeout > 0) {
1665 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001666 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001667 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001668 }
1669
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001670 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001671 goto failed;
1672 }
1673
1674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001680 /* Cancel any potential discoverable timeout that might be
1681 * still active and store new timeout value. The arming of
1682 * the timeout happens in the complete handler.
1683 */
1684 cancel_delayed_work(&hdev->discov_off);
1685 hdev->discov_timeout = timeout;
1686
Johan Hedbergb456f872013-10-19 23:38:22 +03001687 /* Limited discoverable mode */
1688 if (cp->val == 0x02)
1689 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1690 else
1691 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 hci_req_init(&req, hdev);
1694
Johan Hedberg9a43e252013-10-20 19:00:07 +03001695 /* The procedure for LE-only controllers is much simpler - just
1696 * update the advertising data.
1697 */
1698 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1699 goto update_ad;
1700
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001701 scan = SCAN_PAGE;
1702
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001703 if (cp->val) {
1704 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001705
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001706 if (cp->val == 0x02) {
1707 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001708 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001709 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1710 hci_cp.iac_lap[1] = 0x8b;
1711 hci_cp.iac_lap[2] = 0x9e;
1712 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1713 hci_cp.iac_lap[4] = 0x8b;
1714 hci_cp.iac_lap[5] = 0x9e;
1715 } else {
1716 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 hci_cp.num_iac = 1;
1718 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1719 hci_cp.iac_lap[1] = 0x8b;
1720 hci_cp.iac_lap[2] = 0x9e;
1721 }
1722
1723 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1724 (hci_cp.num_iac * 3) + 1, &hci_cp);
1725
1726 scan |= SCAN_INQUIRY;
1727 } else {
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729 }
1730
1731 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001732
Johan Hedberg9a43e252013-10-20 19:00:07 +03001733update_ad:
1734 update_adv_data(&req);
1735
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001736 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001737 if (err < 0)
1738 mgmt_pending_remove(cmd);
1739
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001740failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001742 return err;
1743}
1744
Johan Hedberg406d7802013-03-15 17:07:09 -05001745static void write_fast_connectable(struct hci_request *req, bool enable)
1746{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001747 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001748 struct hci_cp_write_page_scan_activity acp;
1749 u8 type;
1750
Johan Hedberg547003b2013-10-21 16:51:53 +03001751 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1752 return;
1753
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001754 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1755 return;
1756
Johan Hedberg406d7802013-03-15 17:07:09 -05001757 if (enable) {
1758 type = PAGE_SCAN_TYPE_INTERLACED;
1759
1760 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001761 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001762 } else {
1763 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1764
1765 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001766 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001767 }
1768
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001769 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001770
Johan Hedbergbd98b992013-03-15 17:07:13 -05001771 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1772 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1773 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1774 sizeof(acp), &acp);
1775
1776 if (hdev->page_scan_type != type)
1777 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001778}
1779
Johan Hedberg2b76f452013-03-15 17:07:04 -05001780static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1781{
1782 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001784 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001785
1786 BT_DBG("status 0x%02x", status);
1787
1788 hci_dev_lock(hdev);
1789
1790 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1791 if (!cmd)
1792 goto unlock;
1793
Johan Hedberg37438c12013-10-14 16:20:05 +03001794 if (status) {
1795 u8 mgmt_err = mgmt_status(status);
1796 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1797 goto remove_cmd;
1798 }
1799
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001800 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001801 if (cp->val) {
1802 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1803 &hdev->dev_flags);
1804 discov_changed = false;
1805 } else {
1806 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1807 &hdev->dev_flags);
1808 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1809 &hdev->dev_flags);
1810 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001811
Johan Hedberg2b76f452013-03-15 17:07:04 -05001812 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1813
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001814 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001815 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001816 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001817 if (discov_changed)
1818 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001819 hci_update_background_scan(hdev);
1820 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821
Johan Hedberg37438c12013-10-14 16:20:05 +03001822remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823 mgmt_pending_remove(cmd);
1824
1825unlock:
1826 hci_dev_unlock(hdev);
1827}
1828
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001829static int set_connectable_update_settings(struct hci_dev *hdev,
1830 struct sock *sk, u8 val)
1831{
1832 bool changed = false;
1833 int err;
1834
1835 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1836 changed = true;
1837
1838 if (val) {
1839 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1840 } else {
1841 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1842 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1843 }
1844
1845 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1846 if (err < 0)
1847 return err;
1848
Johan Hedberg562064e2014-07-08 16:35:34 +03001849 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001850 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001851 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001852 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001853 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001854
1855 return 0;
1856}
1857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001859 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001860{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001861 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001862 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001863 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001864 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001865 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001867 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001868
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1870 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001871 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001872 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873
Johan Hedberga7e80f22013-01-09 16:05:19 +02001874 if (cp->val != 0x00 && cp->val != 0x01)
1875 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1876 MGMT_STATUS_INVALID_PARAMS);
1877
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001878 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001880 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001881 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 goto failed;
1883 }
1884
1885 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001886 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001888 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889 goto failed;
1890 }
1891
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1893 if (!cmd) {
1894 err = -ENOMEM;
1895 goto failed;
1896 }
1897
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898 hci_req_init(&req, hdev);
1899
Johan Hedberg9a43e252013-10-20 19:00:07 +03001900 /* If BR/EDR is not enabled and we disable advertising as a
1901 * by-product of disabling connectable, we need to update the
1902 * advertising flags.
1903 */
1904 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1905 if (!cp->val) {
1906 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1907 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1908 }
1909 update_adv_data(&req);
1910 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001911 if (cp->val) {
1912 scan = SCAN_PAGE;
1913 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001914 /* If we don't have any whitelist entries just
1915 * disable all scanning. If there are entries
1916 * and we had both page and inquiry scanning
1917 * enabled then fall back to only page scanning.
1918 * Otherwise no changes are needed.
1919 */
1920 if (list_empty(&hdev->whitelist))
1921 scan = SCAN_DISABLED;
1922 else if (test_bit(HCI_ISCAN, &hdev->flags))
1923 scan = SCAN_PAGE;
1924 else
1925 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001926
1927 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001928 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001929 cancel_delayed_work(&hdev->discov_off);
1930 }
1931
1932 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1933 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001934
Johan Hedberg3bd27242014-07-28 20:53:58 +03001935no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001936 /* If we're going from non-connectable to connectable or
1937 * vice-versa when fast connectable is enabled ensure that fast
1938 * connectable gets disabled. write_fast_connectable won't do
1939 * anything if the page scan parameters are already what they
1940 * should be.
1941 */
1942 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001943 write_fast_connectable(&req, false);
1944
Johan Hedberge8b12022014-07-10 10:51:27 +03001945 /* Update the advertising parameters if necessary */
1946 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001947 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001948
Johan Hedberg2b76f452013-03-15 17:07:04 -05001949 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001950 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001952 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001953 err = set_connectable_update_settings(hdev, sk,
1954 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 goto failed;
1956 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
1958failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001959 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001960 return err;
1961}
1962
Johan Hedbergb2939472014-07-30 09:22:23 +03001963static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001964 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001965{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001966 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001967 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001968 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001969
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001970 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
Johan Hedberga7e80f22013-01-09 16:05:19 +02001972 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001973 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001974 MGMT_STATUS_INVALID_PARAMS);
1975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001976 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
1978 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001979 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001981 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982
Johan Hedbergb2939472014-07-30 09:22:23 +03001983 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001984 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001985 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
Marcel Holtmann55594352013-10-06 16:11:57 -07001987 if (changed)
1988 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989
Marcel Holtmann55594352013-10-06 16:11:57 -07001990unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001991 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992 return err;
1993}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001994
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001995static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1996 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001997{
1998 struct mgmt_mode *cp = data;
1999 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002000 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002001 int err;
2002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002003 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002004
Johan Hedberge6fe7982013-10-02 15:45:22 +03002005 status = mgmt_bredr_support(hdev);
2006 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002007 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002008 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002009
Johan Hedberga7e80f22013-01-09 16:05:19 +02002010 if (cp->val != 0x00 && cp->val != 0x01)
2011 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2012 MGMT_STATUS_INVALID_PARAMS);
2013
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002014 hci_dev_lock(hdev);
2015
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002016 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002017 bool changed = false;
2018
2019 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002020 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002021 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2022 changed = true;
2023 }
2024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2026 if (err < 0)
2027 goto failed;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 goto failed;
2033 }
2034
2035 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002037 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002038 goto failed;
2039 }
2040
2041 val = !!cp->val;
2042
2043 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2044 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
2054 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2055 if (err < 0) {
2056 mgmt_pending_remove(cmd);
2057 goto failed;
2058 }
2059
2060failed:
2061 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002062 return err;
2063}
2064
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066{
2067 struct mgmt_mode *cp = data;
2068 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002069 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002070 int err;
2071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002072 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002073
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002074 status = mgmt_bredr_support(hdev);
2075 if (status)
2076 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2077
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002078 if (!lmp_ssp_capable(hdev))
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2080 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002081
Johan Hedberga7e80f22013-01-09 16:05:19 +02002082 if (cp->val != 0x00 && cp->val != 0x01)
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2084 MGMT_STATUS_INVALID_PARAMS);
2085
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002086 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002087
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002088 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002089 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002090
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002091 if (cp->val) {
2092 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2093 &hdev->dev_flags);
2094 } else {
2095 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2096 &hdev->dev_flags);
2097 if (!changed)
2098 changed = test_and_clear_bit(HCI_HS_ENABLED,
2099 &hdev->dev_flags);
2100 else
2101 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002102 }
2103
2104 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2105 if (err < 0)
2106 goto failed;
2107
2108 if (changed)
2109 err = new_settings(hdev, sk);
2110
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002111 goto failed;
2112 }
2113
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002114 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2115 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002116 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2117 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002118 goto failed;
2119 }
2120
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002121 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002122 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2123 goto failed;
2124 }
2125
2126 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2127 if (!cmd) {
2128 err = -ENOMEM;
2129 goto failed;
2130 }
2131
Johan Hedberg37699722014-06-24 14:00:27 +03002132 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2133 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2134 sizeof(cp->val), &cp->val);
2135
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002136 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 if (err < 0) {
2138 mgmt_pending_remove(cmd);
2139 goto failed;
2140 }
2141
2142failed:
2143 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002144 return err;
2145}
2146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002148{
2149 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002150 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002151 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002152 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002155
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 status = mgmt_bredr_support(hdev);
2157 if (status)
2158 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002159
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002160 if (!lmp_ssp_capable(hdev))
2161 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2162 MGMT_STATUS_NOT_SUPPORTED);
2163
2164 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2165 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2166 MGMT_STATUS_REJECTED);
2167
Johan Hedberga7e80f22013-01-09 16:05:19 +02002168 if (cp->val != 0x00 && cp->val != 0x01)
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2170 MGMT_STATUS_INVALID_PARAMS);
2171
Marcel Holtmannee392692013-10-01 22:59:23 -07002172 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002174 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002176 } else {
2177 if (hdev_is_powered(hdev)) {
2178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2179 MGMT_STATUS_REJECTED);
2180 goto unlock;
2181 }
2182
Marcel Holtmannee392692013-10-01 22:59:23 -07002183 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002184 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002185
2186 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2187 if (err < 0)
2188 goto unlock;
2189
2190 if (changed)
2191 err = new_settings(hdev, sk);
2192
2193unlock:
2194 hci_dev_unlock(hdev);
2195 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002196}
2197
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002198static void le_enable_complete(struct hci_dev *hdev, u8 status)
2199{
2200 struct cmd_lookup match = { NULL, hdev };
2201
2202 if (status) {
2203 u8 mgmt_err = mgmt_status(status);
2204
2205 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2206 &mgmt_err);
2207 return;
2208 }
2209
2210 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2211
2212 new_settings(hdev, match.sk);
2213
2214 if (match.sk)
2215 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002216
2217 /* Make sure the controller has a good default for
2218 * advertising data. Restrict the update to when LE
2219 * has actually been enabled. During power on, the
2220 * update in powered_update_hci will take care of it.
2221 */
2222 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2223 struct hci_request req;
2224
2225 hci_dev_lock(hdev);
2226
2227 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002228 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002229 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002230 hci_req_run(&req, NULL);
2231
Johan Hedberga70f4b52014-07-07 15:19:50 +03002232 hci_update_background_scan(hdev);
2233
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002234 hci_dev_unlock(hdev);
2235 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002236}
2237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002238static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239{
2240 struct mgmt_mode *cp = data;
2241 struct hci_cp_write_le_host_supported hci_cp;
2242 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002243 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002244 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002245 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002247 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002249 if (!lmp_le_capable(hdev))
2250 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2251 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002252
Johan Hedberga7e80f22013-01-09 16:05:19 +02002253 if (cp->val != 0x00 && cp->val != 0x01)
2254 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2255 MGMT_STATUS_INVALID_PARAMS);
2256
Johan Hedbergc73eee92013-04-19 18:35:21 +03002257 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002258 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002259 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2260 MGMT_STATUS_REJECTED);
2261
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002262 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002263
2264 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002265 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002266
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002267 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268 bool changed = false;
2269
2270 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2271 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2272 changed = true;
2273 }
2274
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002275 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2276 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002277 changed = true;
2278 }
2279
Johan Hedberg06199cf2012-02-22 16:37:11 +02002280 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2281 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002282 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002283
2284 if (changed)
2285 err = new_settings(hdev, sk);
2286
Johan Hedberg1de028c2012-02-29 19:55:35 -08002287 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002288 }
2289
Johan Hedberg4375f102013-09-25 13:26:10 +03002290 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2291 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002292 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002293 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002294 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295 }
2296
2297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2298 if (!cmd) {
2299 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002300 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 }
2302
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002303 hci_req_init(&req, hdev);
2304
Johan Hedberg06199cf2012-02-22 16:37:11 +02002305 memset(&hci_cp, 0, sizeof(hci_cp));
2306
2307 if (val) {
2308 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002309 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002310 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002312 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002313 }
2314
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002315 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2316 &hci_cp);
2317
2318 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302319 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002320 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321
Johan Hedberg1de028c2012-02-29 19:55:35 -08002322unlock:
2323 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324 return err;
2325}
2326
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002327/* This is a helper function to test for pending mgmt commands that can
2328 * cause CoD or EIR HCI commands. We can only allow one such pending
2329 * mgmt command at a time since otherwise we cannot easily track what
2330 * the current values are, will be, and based on that calculate if a new
2331 * HCI command needs to be sent and if yes with what value.
2332 */
2333static bool pending_eir_or_class(struct hci_dev *hdev)
2334{
2335 struct pending_cmd *cmd;
2336
2337 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2338 switch (cmd->opcode) {
2339 case MGMT_OP_ADD_UUID:
2340 case MGMT_OP_REMOVE_UUID:
2341 case MGMT_OP_SET_DEV_CLASS:
2342 case MGMT_OP_SET_POWERED:
2343 return true;
2344 }
2345 }
2346
2347 return false;
2348}
2349
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002350static const u8 bluetooth_base_uuid[] = {
2351 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2352 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2353};
2354
2355static u8 get_uuid_size(const u8 *uuid)
2356{
2357 u32 val;
2358
2359 if (memcmp(uuid, bluetooth_base_uuid, 12))
2360 return 128;
2361
2362 val = get_unaligned_le32(&uuid[12]);
2363 if (val > 0xffff)
2364 return 32;
2365
2366 return 16;
2367}
2368
Johan Hedberg92da6092013-03-15 17:06:55 -05002369static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2370{
2371 struct pending_cmd *cmd;
2372
2373 hci_dev_lock(hdev);
2374
2375 cmd = mgmt_pending_find(mgmt_op, hdev);
2376 if (!cmd)
2377 goto unlock;
2378
2379 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2380 hdev->dev_class, 3);
2381
2382 mgmt_pending_remove(cmd);
2383
2384unlock:
2385 hci_dev_unlock(hdev);
2386}
2387
2388static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2389{
2390 BT_DBG("status 0x%02x", status);
2391
2392 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2393}
2394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002396{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002397 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002398 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002399 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002400 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 int err;
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002405 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002407 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002410 goto failed;
2411 }
2412
Andre Guedes92c4c202012-06-07 19:05:44 -03002413 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002414 if (!uuid) {
2415 err = -ENOMEM;
2416 goto failed;
2417 }
2418
2419 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002420 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002421 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422
Johan Hedbergde66aa62013-01-27 00:31:27 +02002423 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002424
Johan Hedberg890ea892013-03-15 17:06:52 -05002425 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002426
Johan Hedberg890ea892013-03-15 17:06:52 -05002427 update_class(&req);
2428 update_eir(&req);
2429
Johan Hedberg92da6092013-03-15 17:06:55 -05002430 err = hci_req_run(&req, add_uuid_complete);
2431 if (err < 0) {
2432 if (err != -ENODATA)
2433 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002435 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002436 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002437 goto failed;
2438 }
2439
2440 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002441 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002442 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002443 goto failed;
2444 }
2445
2446 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447
2448failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002449 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002450 return err;
2451}
2452
Johan Hedberg24b78d02012-02-23 23:24:30 +02002453static bool enable_service_cache(struct hci_dev *hdev)
2454{
2455 if (!hdev_is_powered(hdev))
2456 return false;
2457
2458 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002459 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2460 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002461 return true;
2462 }
2463
2464 return false;
2465}
2466
Johan Hedberg92da6092013-03-15 17:06:55 -05002467static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2468{
2469 BT_DBG("status 0x%02x", status);
2470
2471 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2472}
2473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002474static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002475 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002477 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002478 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002479 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480 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 -05002481 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 int err, found;
2483
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002484 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002485
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002486 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002488 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002491 goto unlock;
2492 }
2493
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002494 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002495 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002496
Johan Hedberg24b78d02012-02-23 23:24:30 +02002497 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002498 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002499 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002500 goto unlock;
2501 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002502
Johan Hedberg9246a862012-02-23 21:33:16 +02002503 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002504 }
2505
2506 found = 0;
2507
Johan Hedberg056341c2013-01-27 00:31:30 +02002508 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002509 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2510 continue;
2511
2512 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002513 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 found++;
2515 }
2516
2517 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002518 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002519 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 goto unlock;
2521 }
2522
Johan Hedberg9246a862012-02-23 21:33:16 +02002523update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002525
Johan Hedberg890ea892013-03-15 17:06:52 -05002526 update_class(&req);
2527 update_eir(&req);
2528
Johan Hedberg92da6092013-03-15 17:06:55 -05002529 err = hci_req_run(&req, remove_uuid_complete);
2530 if (err < 0) {
2531 if (err != -ENODATA)
2532 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 goto unlock;
2537 }
2538
2539 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002541 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 goto unlock;
2543 }
2544
2545 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546
2547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002549 return err;
2550}
2551
Johan Hedberg92da6092013-03-15 17:06:55 -05002552static void set_class_complete(struct hci_dev *hdev, u8 status)
2553{
2554 BT_DBG("status 0x%02x", status);
2555
2556 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2557}
2558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002559static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002560 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002561{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002562 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002563 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002564 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002565 int err;
2566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002567 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002568
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002569 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2571 MGMT_STATUS_NOT_SUPPORTED);
2572
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002574
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002575 if (pending_eir_or_class(hdev)) {
2576 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2577 MGMT_STATUS_BUSY);
2578 goto unlock;
2579 }
2580
2581 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2582 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2583 MGMT_STATUS_INVALID_PARAMS);
2584 goto unlock;
2585 }
2586
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002587 hdev->major_class = cp->major;
2588 hdev->minor_class = cp->minor;
2589
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002590 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002591 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002592 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002593 goto unlock;
2594 }
2595
Johan Hedberg890ea892013-03-15 17:06:52 -05002596 hci_req_init(&req, hdev);
2597
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002598 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002599 hci_dev_unlock(hdev);
2600 cancel_delayed_work_sync(&hdev->service_cache);
2601 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002602 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002603 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002604
Johan Hedberg890ea892013-03-15 17:06:52 -05002605 update_class(&req);
2606
Johan Hedberg92da6092013-03-15 17:06:55 -05002607 err = hci_req_run(&req, set_class_complete);
2608 if (err < 0) {
2609 if (err != -ENODATA)
2610 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002611
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002612 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002613 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002614 goto unlock;
2615 }
2616
2617 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002618 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002619 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002620 goto unlock;
2621 }
2622
2623 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002624
Johan Hedbergb5235a62012-02-21 14:32:24 +02002625unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002626 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002627 return err;
2628}
2629
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002630static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002631 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002633 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002634 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2635 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002636 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002637 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002638 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002640 BT_DBG("request for %s", hdev->name);
2641
2642 if (!lmp_bredr_capable(hdev))
2643 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2644 MGMT_STATUS_NOT_SUPPORTED);
2645
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002646 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002647 if (key_count > max_key_count) {
2648 BT_ERR("load_link_keys: too big key_count value %u",
2649 key_count);
2650 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2651 MGMT_STATUS_INVALID_PARAMS);
2652 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653
Johan Hedberg86742e12011-11-07 23:13:38 +02002654 expected_len = sizeof(*cp) + key_count *
2655 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002656 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002657 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002658 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002659 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002660 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661 }
2662
Johan Hedberg4ae14302013-01-20 14:27:13 +02002663 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2664 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2665 MGMT_STATUS_INVALID_PARAMS);
2666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002667 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002668 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002669
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002670 for (i = 0; i < key_count; i++) {
2671 struct mgmt_link_key_info *key = &cp->keys[i];
2672
Marcel Holtmann8e991132014-01-10 02:07:25 -08002673 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002674 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2675 MGMT_STATUS_INVALID_PARAMS);
2676 }
2677
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002678 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679
2680 hci_link_keys_clear(hdev);
2681
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002683 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2684 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002685 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002686 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2687 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002688
2689 if (changed)
2690 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002691
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002692 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002693 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694
Johan Hedberg58e92932014-06-24 14:00:26 +03002695 /* Always ignore debug keys and require a new pairing if
2696 * the user wants to use them.
2697 */
2698 if (key->type == HCI_LK_DEBUG_COMBINATION)
2699 continue;
2700
Johan Hedberg7652ff62014-06-24 13:15:49 +03002701 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2702 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703 }
2704
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002705 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002706
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002707 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002708
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002709 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710}
2711
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002712static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002714{
2715 struct mgmt_ev_device_unpaired ev;
2716
2717 bacpy(&ev.addr.bdaddr, bdaddr);
2718 ev.addr.type = addr_type;
2719
2720 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002721 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002722}
2723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002727 struct mgmt_cp_unpair_device *cp = data;
2728 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002729 struct hci_cp_disconnect dc;
2730 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002731 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732 int err;
2733
Johan Hedberga8a1d192011-11-10 15:54:38 +02002734 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002735 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2736 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002737
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002738 if (!bdaddr_type_is_valid(cp->addr.type))
2739 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2740 MGMT_STATUS_INVALID_PARAMS,
2741 &rp, sizeof(rp));
2742
Johan Hedberg118da702013-01-20 14:27:20 +02002743 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2744 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2745 MGMT_STATUS_INVALID_PARAMS,
2746 &rp, sizeof(rp));
2747
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002748 hci_dev_lock(hdev);
2749
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002750 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002751 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002752 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002753 goto unlock;
2754 }
2755
Johan Hedberge0b2b272014-02-18 17:14:31 +02002756 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002757 /* If disconnection is requested, then look up the
2758 * connection. If the remote device is connected, it
2759 * will be later used to terminate the link.
2760 *
2761 * Setting it to NULL explicitly will cause no
2762 * termination of the link.
2763 */
2764 if (cp->disconnect)
2765 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2766 &cp->addr.bdaddr);
2767 else
2768 conn = NULL;
2769
Johan Hedberg124f6e32012-02-09 13:50:12 +02002770 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002771 } else {
2772 u8 addr_type;
2773
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002774 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2775 &cp->addr.bdaddr);
2776 if (conn) {
2777 /* Defer clearing up the connection parameters
2778 * until closing to give a chance of keeping
2779 * them if a repairing happens.
2780 */
2781 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2782
2783 /* If disconnection is not requested, then
2784 * clear the connection variable so that the
2785 * link is not terminated.
2786 */
2787 if (!cp->disconnect)
2788 conn = NULL;
2789 }
2790
Johan Hedberge0b2b272014-02-18 17:14:31 +02002791 if (cp->addr.type == BDADDR_LE_PUBLIC)
2792 addr_type = ADDR_LE_DEV_PUBLIC;
2793 else
2794 addr_type = ADDR_LE_DEV_RANDOM;
2795
Johan Hedberga7ec7332014-02-18 17:14:35 +02002796 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2797
Johan Hedberge0b2b272014-02-18 17:14:31 +02002798 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2799 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002800
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002801 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002802 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002803 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002804 goto unlock;
2805 }
2806
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002807 /* If the connection variable is set, then termination of the
2808 * link is requested.
2809 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002810 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002811 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002812 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002813 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002814 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002815 }
2816
Johan Hedberg124f6e32012-02-09 13:50:12 +02002817 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002818 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002819 if (!cmd) {
2820 err = -ENOMEM;
2821 goto unlock;
2822 }
2823
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002824 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002825 dc.reason = 0x13; /* Remote User Terminated Connection */
2826 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2827 if (err < 0)
2828 mgmt_pending_remove(cmd);
2829
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002830unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002831 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002832 return err;
2833}
2834
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002835static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002836 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002837{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002838 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002839 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002840 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002841 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002842 int err;
2843
2844 BT_DBG("");
2845
Johan Hedberg06a63b12013-01-20 14:27:21 +02002846 memset(&rp, 0, sizeof(rp));
2847 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2848 rp.addr.type = cp->addr.type;
2849
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002850 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002851 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2852 MGMT_STATUS_INVALID_PARAMS,
2853 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002854
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002855 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002856
2857 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002858 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2859 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002860 goto failed;
2861 }
2862
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002863 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002864 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2865 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002866 goto failed;
2867 }
2868
Andre Guedes591f47f2012-04-24 21:02:49 -03002869 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002870 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2871 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002872 else
2873 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002874
Vishal Agarwalf9607272012-06-13 05:32:43 +05302875 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002876 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2877 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002878 goto failed;
2879 }
2880
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002881 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002882 if (!cmd) {
2883 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002884 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002885 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002886
Johan Hedbergf5818c22014-12-05 13:36:02 +02002887 cmd->cmd_complete = generic_cmd_complete;
2888
Johan Hedberge3f2f922014-08-18 20:33:33 +03002889 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002890 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002891 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002892
2893failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002894 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002895 return err;
2896}
2897
Andre Guedes57c14772012-04-24 21:02:50 -03002898static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002899{
2900 switch (link_type) {
2901 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002902 switch (addr_type) {
2903 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002904 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002905
Johan Hedberg48264f02011-11-09 13:58:58 +02002906 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002907 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002908 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002909 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002910
Johan Hedberg4c659c32011-11-07 23:13:39 +02002911 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002912 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002913 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002914 }
2915}
2916
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002917static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2918 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002919{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002920 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002921 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002922 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002923 int err;
2924 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002925
2926 BT_DBG("");
2927
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002928 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002929
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002930 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002931 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002932 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002933 goto unlock;
2934 }
2935
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002936 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002937 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2938 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002939 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002940 }
2941
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002942 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002943 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002944 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002945 err = -ENOMEM;
2946 goto unlock;
2947 }
2948
Johan Hedberg2784eb42011-01-21 13:56:35 +02002949 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002950 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002951 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2952 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002953 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002954 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002955 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002956 continue;
2957 i++;
2958 }
2959
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002960 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002961
Johan Hedberg4c659c32011-11-07 23:13:39 +02002962 /* Recalculate length in case of filtered SCO connections, etc */
2963 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002964
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002965 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002966 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002967
Johan Hedberga38528f2011-01-22 06:46:43 +02002968 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002969
2970unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002971 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002972 return err;
2973}
2974
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002975static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002977{
2978 struct pending_cmd *cmd;
2979 int err;
2980
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002981 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002983 if (!cmd)
2984 return -ENOMEM;
2985
Johan Hedbergd8457692012-02-17 14:24:57 +02002986 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002987 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002988 if (err < 0)
2989 mgmt_pending_remove(cmd);
2990
2991 return err;
2992}
2993
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002994static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002995 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002996{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002997 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002998 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002999 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003000 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003001 int err;
3002
3003 BT_DBG("");
3004
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003005 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003006
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003007 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003008 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003009 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003010 goto failed;
3011 }
3012
Johan Hedbergd8457692012-02-17 14:24:57 +02003013 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003014 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003015 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003016 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003017 goto failed;
3018 }
3019
3020 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003021 struct mgmt_cp_pin_code_neg_reply ncp;
3022
3023 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003024
3025 BT_ERR("PIN code is not 16 bytes long");
3026
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003027 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003028 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003029 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003030 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003031
3032 goto failed;
3033 }
3034
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003035 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003036 if (!cmd) {
3037 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003038 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003039 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003041 cmd->cmd_complete = addr_cmd_complete;
3042
Johan Hedbergd8457692012-02-17 14:24:57 +02003043 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003044 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003045 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003046
3047 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3048 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003049 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003050
3051failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003052 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003053 return err;
3054}
3055
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003056static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3057 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003058{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003059 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003060
3061 BT_DBG("");
3062
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003063 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3064 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3065 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3066
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003067 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003068
3069 hdev->io_capability = cp->io_capability;
3070
3071 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003072 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003073
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003074 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003075
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003076 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3077 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003078}
3079
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003080static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003081{
3082 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003083 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003084
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003085 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003086 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3087 continue;
3088
Johan Hedberge9a416b2011-02-19 12:05:56 -03003089 if (cmd->user_data != conn)
3090 continue;
3091
3092 return cmd;
3093 }
3094
3095 return NULL;
3096}
3097
3098static void pairing_complete(struct pending_cmd *cmd, u8 status)
3099{
3100 struct mgmt_rp_pair_device rp;
3101 struct hci_conn *conn = cmd->user_data;
3102
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003103 bacpy(&rp.addr.bdaddr, &conn->dst);
3104 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003105
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003106 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003107 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003108
3109 /* So we don't get further callbacks for this connection */
3110 conn->connect_cfm_cb = NULL;
3111 conn->security_cfm_cb = NULL;
3112 conn->disconn_cfm_cb = NULL;
3113
David Herrmann76a68ba2013-04-06 20:28:37 +02003114 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003115 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003116
Johan Hedberga664b5b2011-02-19 12:06:02 -03003117 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003118
3119 /* The device is paired so there is no need to remove
3120 * its connection parameters anymore.
3121 */
3122 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003123}
3124
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003125void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3126{
3127 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3128 struct pending_cmd *cmd;
3129
3130 cmd = find_pairing(conn);
3131 if (cmd)
3132 pairing_complete(cmd, status);
3133}
3134
Johan Hedberge9a416b2011-02-19 12:05:56 -03003135static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3136{
3137 struct pending_cmd *cmd;
3138
3139 BT_DBG("status %u", status);
3140
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003141 cmd = find_pairing(conn);
3142 if (!cmd)
3143 BT_DBG("Unable to find a pending command");
3144 else
Johan Hedberge2113262012-02-18 15:20:03 +02003145 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003146}
3147
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003148static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303149{
3150 struct pending_cmd *cmd;
3151
3152 BT_DBG("status %u", status);
3153
3154 if (!status)
3155 return;
3156
3157 cmd = find_pairing(conn);
3158 if (!cmd)
3159 BT_DBG("Unable to find a pending command");
3160 else
3161 pairing_complete(cmd, mgmt_status(status));
3162}
3163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003164static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003165 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003167 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003168 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003169 struct pending_cmd *cmd;
3170 u8 sec_level, auth_type;
3171 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003172 int err;
3173
3174 BT_DBG("");
3175
Szymon Jancf950a30e2013-01-18 12:48:07 +01003176 memset(&rp, 0, sizeof(rp));
3177 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3178 rp.addr.type = cp->addr.type;
3179
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003180 if (!bdaddr_type_is_valid(cp->addr.type))
3181 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3182 MGMT_STATUS_INVALID_PARAMS,
3183 &rp, sizeof(rp));
3184
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003185 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3186 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3187 MGMT_STATUS_INVALID_PARAMS,
3188 &rp, sizeof(rp));
3189
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003190 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003191
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003192 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003193 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3194 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003195 goto unlock;
3196 }
3197
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003198 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003199 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003200
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003201 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003202 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3203 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003204 } else {
3205 u8 addr_type;
3206
3207 /* Convert from L2CAP channel address type to HCI address type
3208 */
3209 if (cp->addr.type == BDADDR_LE_PUBLIC)
3210 addr_type = ADDR_LE_DEV_PUBLIC;
3211 else
3212 addr_type = ADDR_LE_DEV_RANDOM;
3213
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003214 /* When pairing a new device, it is expected to remember
3215 * this device for future connections. Adding the connection
3216 * parameter information ahead of time allows tracking
3217 * of the slave preferred values and will speed up any
3218 * further connection establishment.
3219 *
3220 * If connection parameters already exist, then they
3221 * will be kept and this function does nothing.
3222 */
3223 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3224
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003225 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003226 sec_level, HCI_LE_CONN_TIMEOUT,
3227 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003228 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003229
Ville Tervo30e76272011-02-22 16:10:53 -03003230 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003231 int status;
3232
3233 if (PTR_ERR(conn) == -EBUSY)
3234 status = MGMT_STATUS_BUSY;
3235 else
3236 status = MGMT_STATUS_CONNECT_FAILED;
3237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003238 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003239 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003240 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003241 goto unlock;
3242 }
3243
3244 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003245 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003246 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003247 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003248 goto unlock;
3249 }
3250
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003251 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003252 if (!cmd) {
3253 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003254 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003255 goto unlock;
3256 }
3257
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003258 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003259 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003260 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003261 conn->security_cfm_cb = pairing_complete_cb;
3262 conn->disconn_cfm_cb = pairing_complete_cb;
3263 } else {
3264 conn->connect_cfm_cb = le_pairing_complete_cb;
3265 conn->security_cfm_cb = le_pairing_complete_cb;
3266 conn->disconn_cfm_cb = le_pairing_complete_cb;
3267 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003268
Johan Hedberge9a416b2011-02-19 12:05:56 -03003269 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003270 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003271
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003272 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003273 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003274 pairing_complete(cmd, 0);
3275
3276 err = 0;
3277
3278unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003279 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003280 return err;
3281}
3282
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003283static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3284 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003285{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003286 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003287 struct pending_cmd *cmd;
3288 struct hci_conn *conn;
3289 int err;
3290
3291 BT_DBG("");
3292
Johan Hedberg28424702012-02-02 04:02:29 +02003293 hci_dev_lock(hdev);
3294
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003295 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003296 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003297 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003298 goto unlock;
3299 }
3300
Johan Hedberg28424702012-02-02 04:02:29 +02003301 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3302 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003303 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003304 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003305 goto unlock;
3306 }
3307
3308 conn = cmd->user_data;
3309
3310 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003311 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003312 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003313 goto unlock;
3314 }
3315
3316 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3317
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003318 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003319 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003320unlock:
3321 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003322 return err;
3323}
3324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003325static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003326 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003327 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003328{
Johan Hedberga5c29682011-02-19 12:05:57 -03003329 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003330 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003331 int err;
3332
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003333 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003334
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003335 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003336 err = cmd_complete(sk, hdev->id, mgmt_op,
3337 MGMT_STATUS_NOT_POWERED, addr,
3338 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003339 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003340 }
3341
Johan Hedberg1707c602013-03-15 17:07:15 -05003342 if (addr->type == BDADDR_BREDR)
3343 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003344 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003345 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003346
Johan Hedberg272d90d2012-02-09 15:26:12 +02003347 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003348 err = cmd_complete(sk, hdev->id, mgmt_op,
3349 MGMT_STATUS_NOT_CONNECTED, addr,
3350 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003351 goto done;
3352 }
3353
Johan Hedberg1707c602013-03-15 17:07:15 -05003354 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003355 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003356 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003357 err = cmd_complete(sk, hdev->id, mgmt_op,
3358 MGMT_STATUS_SUCCESS, addr,
3359 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003360 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003361 err = cmd_complete(sk, hdev->id, mgmt_op,
3362 MGMT_STATUS_FAILED, addr,
3363 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003364
Brian Gix47c15e22011-11-16 13:53:14 -08003365 goto done;
3366 }
3367
Johan Hedberg1707c602013-03-15 17:07:15 -05003368 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003369 if (!cmd) {
3370 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003371 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003372 }
3373
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003374 cmd->cmd_complete = addr_cmd_complete;
3375
Brian Gix0df4c182011-11-16 13:53:13 -08003376 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003377 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3378 struct hci_cp_user_passkey_reply cp;
3379
Johan Hedberg1707c602013-03-15 17:07:15 -05003380 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003381 cp.passkey = passkey;
3382 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3383 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003384 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3385 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003386
Johan Hedberga664b5b2011-02-19 12:06:02 -03003387 if (err < 0)
3388 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003389
Brian Gix0df4c182011-11-16 13:53:13 -08003390done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003391 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003392 return err;
3393}
3394
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303395static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3396 void *data, u16 len)
3397{
3398 struct mgmt_cp_pin_code_neg_reply *cp = data;
3399
3400 BT_DBG("");
3401
Johan Hedberg1707c602013-03-15 17:07:15 -05003402 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303403 MGMT_OP_PIN_CODE_NEG_REPLY,
3404 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3405}
3406
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003407static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3408 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003409{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003410 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003411
3412 BT_DBG("");
3413
3414 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003415 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003416 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003417
Johan Hedberg1707c602013-03-15 17:07:15 -05003418 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003419 MGMT_OP_USER_CONFIRM_REPLY,
3420 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003421}
3422
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003423static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003424 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003425{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003426 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003427
3428 BT_DBG("");
3429
Johan Hedberg1707c602013-03-15 17:07:15 -05003430 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003431 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3432 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003433}
3434
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003435static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3436 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003437{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003438 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003439
3440 BT_DBG("");
3441
Johan Hedberg1707c602013-03-15 17:07:15 -05003442 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003443 MGMT_OP_USER_PASSKEY_REPLY,
3444 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003445}
3446
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003447static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003448 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003449{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003450 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003451
3452 BT_DBG("");
3453
Johan Hedberg1707c602013-03-15 17:07:15 -05003454 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003455 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3456 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003457}
3458
Johan Hedberg13928972013-03-15 17:07:00 -05003459static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003460{
Johan Hedberg13928972013-03-15 17:07:00 -05003461 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003462 struct hci_cp_write_local_name cp;
3463
Johan Hedberg13928972013-03-15 17:07:00 -05003464 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003465
Johan Hedberg890ea892013-03-15 17:06:52 -05003466 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003467}
3468
Johan Hedberg13928972013-03-15 17:07:00 -05003469static void set_name_complete(struct hci_dev *hdev, u8 status)
3470{
3471 struct mgmt_cp_set_local_name *cp;
3472 struct pending_cmd *cmd;
3473
3474 BT_DBG("status 0x%02x", status);
3475
3476 hci_dev_lock(hdev);
3477
3478 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3479 if (!cmd)
3480 goto unlock;
3481
3482 cp = cmd->param;
3483
3484 if (status)
3485 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3486 mgmt_status(status));
3487 else
3488 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3489 cp, sizeof(*cp));
3490
3491 mgmt_pending_remove(cmd);
3492
3493unlock:
3494 hci_dev_unlock(hdev);
3495}
3496
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003497static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003498 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003499{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003500 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003501 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003502 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003503 int err;
3504
3505 BT_DBG("");
3506
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003507 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003508
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003509 /* If the old values are the same as the new ones just return a
3510 * direct command complete event.
3511 */
3512 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3513 !memcmp(hdev->short_name, cp->short_name,
3514 sizeof(hdev->short_name))) {
3515 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3516 data, len);
3517 goto failed;
3518 }
3519
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003520 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003521
Johan Hedbergb5235a62012-02-21 14:32:24 +02003522 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003523 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003524
3525 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003526 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003527 if (err < 0)
3528 goto failed;
3529
3530 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003531 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003532
Johan Hedbergb5235a62012-02-21 14:32:24 +02003533 goto failed;
3534 }
3535
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003536 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003537 if (!cmd) {
3538 err = -ENOMEM;
3539 goto failed;
3540 }
3541
Johan Hedberg13928972013-03-15 17:07:00 -05003542 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3543
Johan Hedberg890ea892013-03-15 17:06:52 -05003544 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003545
3546 if (lmp_bredr_capable(hdev)) {
3547 update_name(&req);
3548 update_eir(&req);
3549 }
3550
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003551 /* The name is stored in the scan response data and so
3552 * no need to udpate the advertising data here.
3553 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003554 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003555 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003556
Johan Hedberg13928972013-03-15 17:07:00 -05003557 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003558 if (err < 0)
3559 mgmt_pending_remove(cmd);
3560
3561failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003562 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003563 return err;
3564}
3565
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003566static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003567 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003568{
Szymon Jancc35938b2011-03-22 13:12:21 +01003569 struct pending_cmd *cmd;
3570 int err;
3571
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003572 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003573
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003574 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003575
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003576 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003577 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003578 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003579 goto unlock;
3580 }
3581
Andre Guedes9a1a1992012-07-24 15:03:48 -03003582 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003583 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003584 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003585 goto unlock;
3586 }
3587
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003588 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003589 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003590 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003591 goto unlock;
3592 }
3593
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003594 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003595 if (!cmd) {
3596 err = -ENOMEM;
3597 goto unlock;
3598 }
3599
Johan Hedberg710f11c2014-05-26 11:21:22 +03003600 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003601 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3602 0, NULL);
3603 else
3604 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3605
Szymon Jancc35938b2011-03-22 13:12:21 +01003606 if (err < 0)
3607 mgmt_pending_remove(cmd);
3608
3609unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003610 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003611 return err;
3612}
3613
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003614static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003615 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003616{
Szymon Janc2763eda2011-03-22 13:12:22 +01003617 int err;
3618
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003619 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003620
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003621 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003622
Marcel Holtmannec109112014-01-10 02:07:30 -08003623 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3624 struct mgmt_cp_add_remote_oob_data *cp = data;
3625 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003626
Johan Hedbergc19a4952014-11-17 20:52:19 +02003627 if (cp->addr.type != BDADDR_BREDR) {
3628 err = cmd_complete(sk, hdev->id,
3629 MGMT_OP_ADD_REMOTE_OOB_DATA,
3630 MGMT_STATUS_INVALID_PARAMS,
3631 &cp->addr, sizeof(cp->addr));
3632 goto unlock;
3633 }
3634
Marcel Holtmannec109112014-01-10 02:07:30 -08003635 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003636 cp->addr.type, cp->hash,
3637 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003638 if (err < 0)
3639 status = MGMT_STATUS_FAILED;
3640 else
3641 status = MGMT_STATUS_SUCCESS;
3642
3643 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3644 status, &cp->addr, sizeof(cp->addr));
3645 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3646 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003647 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003648 u8 status;
3649
Johan Hedbergc19a4952014-11-17 20:52:19 +02003650 if (cp->addr.type != BDADDR_BREDR) {
3651 err = cmd_complete(sk, hdev->id,
3652 MGMT_OP_ADD_REMOTE_OOB_DATA,
3653 MGMT_STATUS_INVALID_PARAMS,
3654 &cp->addr, sizeof(cp->addr));
3655 goto unlock;
3656 }
3657
Johan Hedberg86df9202014-10-26 20:52:27 +01003658 if (bdaddr_type_is_le(cp->addr.type)) {
3659 rand192 = NULL;
3660 hash192 = NULL;
3661 } else {
3662 rand192 = cp->rand192;
3663 hash192 = cp->hash192;
3664 }
3665
Johan Hedberg81328d52014-10-26 20:33:47 +01003666 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003667 cp->addr.type, hash192, rand192,
3668 cp->hash256, cp->rand256);
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 {
3677 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3678 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3679 MGMT_STATUS_INVALID_PARAMS);
3680 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003681
Johan Hedbergc19a4952014-11-17 20:52:19 +02003682unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003683 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003684 return err;
3685}
3686
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003687static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003688 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003689{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003690 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003691 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003692 int err;
3693
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003694 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003695
Johan Hedbergc19a4952014-11-17 20:52:19 +02003696 if (cp->addr.type != BDADDR_BREDR)
3697 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3698 MGMT_STATUS_INVALID_PARAMS,
3699 &cp->addr, sizeof(cp->addr));
3700
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003701 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003702
Johan Hedbergeedbd582014-11-15 09:34:23 +02003703 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3704 hci_remote_oob_data_clear(hdev);
3705 status = MGMT_STATUS_SUCCESS;
3706 goto done;
3707 }
3708
Johan Hedberg6928a922014-10-26 20:46:09 +01003709 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003710 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003711 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003712 else
Szymon Janca6785be2012-12-13 15:11:21 +01003713 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003714
Johan Hedbergeedbd582014-11-15 09:34:23 +02003715done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003716 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003717 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003718
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003719 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003720 return err;
3721}
3722
Marcel Holtmann80190442014-12-04 11:36:36 +01003723static bool trigger_discovery(struct hci_request *req, u8 *status)
3724{
3725 struct hci_dev *hdev = req->hdev;
3726 struct hci_cp_le_set_scan_param param_cp;
3727 struct hci_cp_le_set_scan_enable enable_cp;
3728 struct hci_cp_inquiry inq_cp;
3729 /* General inquiry access code (GIAC) */
3730 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3731 u8 own_addr_type;
3732 int err;
3733
3734 switch (hdev->discovery.type) {
3735 case DISCOV_TYPE_BREDR:
3736 *status = mgmt_bredr_support(hdev);
3737 if (*status)
3738 return false;
3739
3740 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3741 *status = MGMT_STATUS_BUSY;
3742 return false;
3743 }
3744
3745 hci_inquiry_cache_flush(hdev);
3746
3747 memset(&inq_cp, 0, sizeof(inq_cp));
3748 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3749 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3750 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3751 break;
3752
3753 case DISCOV_TYPE_LE:
3754 case DISCOV_TYPE_INTERLEAVED:
3755 *status = mgmt_le_support(hdev);
3756 if (*status)
3757 return false;
3758
3759 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3760 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3761 *status = MGMT_STATUS_NOT_SUPPORTED;
3762 return false;
3763 }
3764
3765 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3766 /* Don't let discovery abort an outgoing
3767 * connection attempt that's using directed
3768 * advertising.
3769 */
3770 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3771 BT_CONNECT)) {
3772 *status = MGMT_STATUS_REJECTED;
3773 return false;
3774 }
3775
3776 disable_advertising(req);
3777 }
3778
3779 /* If controller is scanning, it means the background scanning
3780 * is running. Thus, we should temporarily stop it in order to
3781 * set the discovery scanning parameters.
3782 */
3783 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3784 hci_req_add_le_scan_disable(req);
3785
3786 memset(&param_cp, 0, sizeof(param_cp));
3787
3788 /* All active scans will be done with either a resolvable
3789 * private address (when privacy feature has been enabled)
3790 * or unresolvable private address.
3791 */
3792 err = hci_update_random_address(req, true, &own_addr_type);
3793 if (err < 0) {
3794 *status = MGMT_STATUS_FAILED;
3795 return false;
3796 }
3797
3798 param_cp.type = LE_SCAN_ACTIVE;
3799 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3800 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3801 param_cp.own_address_type = own_addr_type;
3802 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3803 &param_cp);
3804
3805 memset(&enable_cp, 0, sizeof(enable_cp));
3806 enable_cp.enable = LE_SCAN_ENABLE;
3807 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3808 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3809 &enable_cp);
3810 break;
3811
3812 default:
3813 *status = MGMT_STATUS_INVALID_PARAMS;
3814 return false;
3815 }
3816
3817 return true;
3818}
3819
Andre Guedes7c307722013-04-30 15:29:28 -03003820static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3821{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003822 struct pending_cmd *cmd;
3823 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003824
Andre Guedes7c307722013-04-30 15:29:28 -03003825 BT_DBG("status %d", status);
3826
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003827 hci_dev_lock(hdev);
3828
3829 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003830 if (!cmd)
3831 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3832
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003833 if (cmd) {
3834 u8 type = hdev->discovery.type;
3835
3836 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
3837 mgmt_status(status), &type, sizeof(type));
3838 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003839 }
3840
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003841 if (status) {
3842 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3843 goto unlock;
3844 }
3845
Andre Guedes7c307722013-04-30 15:29:28 -03003846 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003847
3848 switch (hdev->discovery.type) {
3849 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003850 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003851 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003852 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003853 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003854 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003855 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003856 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003857 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003858 default:
3859 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003860 timeout = 0;
3861 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003862 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003863
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003864 if (timeout)
3865 queue_delayed_work(hdev->workqueue,
3866 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003867
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003868unlock:
3869 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003870}
3871
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003872static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003873 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003874{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003875 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003876 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003877 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003878 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003879 int err;
3880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003881 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003882
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003883 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003884
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003885 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003886 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3887 MGMT_STATUS_NOT_POWERED,
3888 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003889 goto failed;
3890 }
3891
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003892 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3893 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003894 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3895 MGMT_STATUS_BUSY, &cp->type,
3896 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003897 goto failed;
3898 }
3899
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003900 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003901 if (!cmd) {
3902 err = -ENOMEM;
3903 goto failed;
3904 }
3905
Marcel Holtmann22078802014-12-05 11:45:22 +01003906 /* Clear the discovery filter first to free any previously
3907 * allocated memory for the UUID list.
3908 */
3909 hci_discovery_filter_clear(hdev);
3910
Andre Guedes4aab14e2012-02-17 20:39:36 -03003911 hdev->discovery.type = cp->type;
3912
Andre Guedes7c307722013-04-30 15:29:28 -03003913 hci_req_init(&req, hdev);
3914
Marcel Holtmann80190442014-12-04 11:36:36 +01003915 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003916 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003917 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003918 mgmt_pending_remove(cmd);
3919 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003920 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003921
Andre Guedes7c307722013-04-30 15:29:28 -03003922 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003923 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003924 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003925 goto failed;
3926 }
3927
3928 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003929
3930failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003931 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003932 return err;
3933}
3934
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003935static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3936 void *data, u16 len)
3937{
3938 struct mgmt_cp_start_service_discovery *cp = data;
3939 struct pending_cmd *cmd;
3940 struct hci_request req;
3941 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3942 u16 uuid_count, expected_len;
3943 u8 status;
3944 int err;
3945
3946 BT_DBG("%s", hdev->name);
3947
3948 hci_dev_lock(hdev);
3949
3950 if (!hdev_is_powered(hdev)) {
3951 err = cmd_complete(sk, hdev->id,
3952 MGMT_OP_START_SERVICE_DISCOVERY,
3953 MGMT_STATUS_NOT_POWERED,
3954 &cp->type, sizeof(cp->type));
3955 goto failed;
3956 }
3957
3958 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3959 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3960 err = cmd_complete(sk, hdev->id,
3961 MGMT_OP_START_SERVICE_DISCOVERY,
3962 MGMT_STATUS_BUSY, &cp->type,
3963 sizeof(cp->type));
3964 goto failed;
3965 }
3966
3967 uuid_count = __le16_to_cpu(cp->uuid_count);
3968 if (uuid_count > max_uuid_count) {
3969 BT_ERR("service_discovery: too big uuid_count value %u",
3970 uuid_count);
3971 err = cmd_complete(sk, hdev->id,
3972 MGMT_OP_START_SERVICE_DISCOVERY,
3973 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3974 sizeof(cp->type));
3975 goto failed;
3976 }
3977
3978 expected_len = sizeof(*cp) + uuid_count * 16;
3979 if (expected_len != len) {
3980 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3981 expected_len, len);
3982 err = cmd_complete(sk, hdev->id,
3983 MGMT_OP_START_SERVICE_DISCOVERY,
3984 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3985 sizeof(cp->type));
3986 goto failed;
3987 }
3988
3989 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
3990 hdev, NULL, 0);
3991 if (!cmd) {
3992 err = -ENOMEM;
3993 goto failed;
3994 }
3995
Marcel Holtmann22078802014-12-05 11:45:22 +01003996 /* Clear the discovery filter first to free any previously
3997 * allocated memory for the UUID list.
3998 */
3999 hci_discovery_filter_clear(hdev);
4000
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004001 hdev->discovery.type = cp->type;
4002 hdev->discovery.rssi = cp->rssi;
4003 hdev->discovery.uuid_count = uuid_count;
4004
4005 if (uuid_count > 0) {
4006 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4007 GFP_KERNEL);
4008 if (!hdev->discovery.uuids) {
4009 err = cmd_complete(sk, hdev->id,
4010 MGMT_OP_START_SERVICE_DISCOVERY,
4011 MGMT_STATUS_FAILED,
4012 &cp->type, sizeof(cp->type));
4013 mgmt_pending_remove(cmd);
4014 goto failed;
4015 }
4016 }
4017
4018 hci_req_init(&req, hdev);
4019
4020 if (!trigger_discovery(&req, &status)) {
4021 err = cmd_complete(sk, hdev->id,
4022 MGMT_OP_START_SERVICE_DISCOVERY,
4023 status, &cp->type, sizeof(cp->type));
4024 mgmt_pending_remove(cmd);
4025 goto failed;
4026 }
4027
4028 err = hci_req_run(&req, start_discovery_complete);
4029 if (err < 0) {
4030 mgmt_pending_remove(cmd);
4031 goto failed;
4032 }
4033
4034 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4035
4036failed:
4037 hci_dev_unlock(hdev);
4038 return err;
4039}
4040
Andre Guedes0e05bba2013-04-30 15:29:33 -03004041static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4042{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004043 struct pending_cmd *cmd;
4044
Andre Guedes0e05bba2013-04-30 15:29:33 -03004045 BT_DBG("status %d", status);
4046
4047 hci_dev_lock(hdev);
4048
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004049 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4050 if (cmd) {
4051 u8 type = hdev->discovery.type;
4052
4053 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
4054 mgmt_status(status), &type, sizeof(type));
4055 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004056 }
4057
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004058 if (!status)
4059 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004060
Andre Guedes0e05bba2013-04-30 15:29:33 -03004061 hci_dev_unlock(hdev);
4062}
4063
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004064static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004065 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004066{
Johan Hedbergd9306502012-02-20 23:25:18 +02004067 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004068 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004069 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004070 int err;
4071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004072 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004073
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004074 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004075
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004076 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004077 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004078 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4079 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004080 goto unlock;
4081 }
4082
4083 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004084 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004085 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4086 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004087 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004088 }
4089
Johan Hedberg2e58ef32011-11-08 20:40:15 +02004090 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04004091 if (!cmd) {
4092 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004093 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004094 }
4095
Andre Guedes0e05bba2013-04-30 15:29:33 -03004096 hci_req_init(&req, hdev);
4097
Johan Hedberg21a60d32014-06-10 14:05:58 +03004098 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004099
Johan Hedberg21a60d32014-06-10 14:05:58 +03004100 err = hci_req_run(&req, stop_discovery_complete);
4101 if (!err) {
4102 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004103 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004104 }
4105
Johan Hedberg21a60d32014-06-10 14:05:58 +03004106 mgmt_pending_remove(cmd);
4107
4108 /* If no HCI commands were sent we're done */
4109 if (err == -ENODATA) {
4110 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4111 &mgmt_cp->type, sizeof(mgmt_cp->type));
4112 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4113 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004114
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004115unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004116 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004117 return err;
4118}
4119
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004120static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004121 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004122{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004123 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004124 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004125 int err;
4126
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004127 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004128
Johan Hedberg561aafb2012-01-04 13:31:59 +02004129 hci_dev_lock(hdev);
4130
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004131 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004132 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4133 MGMT_STATUS_FAILED, &cp->addr,
4134 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004135 goto failed;
4136 }
4137
Johan Hedberga198e7b2012-02-17 14:27:06 +02004138 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004139 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004140 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4141 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4142 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004143 goto failed;
4144 }
4145
4146 if (cp->name_known) {
4147 e->name_state = NAME_KNOWN;
4148 list_del(&e->list);
4149 } else {
4150 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004151 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004152 }
4153
Johan Hedberge3846622013-01-09 15:29:33 +02004154 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4155 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004156
4157failed:
4158 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004159 return err;
4160}
4161
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004162static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004163 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004164{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004165 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004166 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004167 int err;
4168
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004169 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004170
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004171 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004172 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4173 MGMT_STATUS_INVALID_PARAMS,
4174 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004175
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004176 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004177
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004178 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4179 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004180 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004181 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004182 goto done;
4183 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004184
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004185 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4186 sk);
4187 status = MGMT_STATUS_SUCCESS;
4188
4189done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004190 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004191 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004192
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004193 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004194
4195 return err;
4196}
4197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004198static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004199 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004200{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004201 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004202 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004203 int err;
4204
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004205 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004206
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004207 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004208 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4209 MGMT_STATUS_INVALID_PARAMS,
4210 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004211
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004212 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004213
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004214 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4215 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004216 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004217 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004218 goto done;
4219 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004220
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004221 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4222 sk);
4223 status = MGMT_STATUS_SUCCESS;
4224
4225done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004226 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004227 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004228
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004229 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004230
4231 return err;
4232}
4233
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004234static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4235 u16 len)
4236{
4237 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004238 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004239 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004240 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004241
4242 BT_DBG("%s", hdev->name);
4243
Szymon Jancc72d4b82012-03-16 16:02:57 +01004244 source = __le16_to_cpu(cp->source);
4245
4246 if (source > 0x0002)
4247 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4248 MGMT_STATUS_INVALID_PARAMS);
4249
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004250 hci_dev_lock(hdev);
4251
Szymon Jancc72d4b82012-03-16 16:02:57 +01004252 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004253 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4254 hdev->devid_product = __le16_to_cpu(cp->product);
4255 hdev->devid_version = __le16_to_cpu(cp->version);
4256
4257 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4258
Johan Hedberg890ea892013-03-15 17:06:52 -05004259 hci_req_init(&req, hdev);
4260 update_eir(&req);
4261 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004262
4263 hci_dev_unlock(hdev);
4264
4265 return err;
4266}
4267
Johan Hedberg4375f102013-09-25 13:26:10 +03004268static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4269{
4270 struct cmd_lookup match = { NULL, hdev };
4271
4272 if (status) {
4273 u8 mgmt_err = mgmt_status(status);
4274
4275 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4276 cmd_status_rsp, &mgmt_err);
4277 return;
4278 }
4279
Johan Hedbergc93bd152014-07-08 15:07:48 +03004280 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4281 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4282 else
4283 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4284
Johan Hedberg4375f102013-09-25 13:26:10 +03004285 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4286 &match);
4287
4288 new_settings(hdev, match.sk);
4289
4290 if (match.sk)
4291 sock_put(match.sk);
4292}
4293
Marcel Holtmann21b51872013-10-10 09:47:53 -07004294static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4295 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004296{
4297 struct mgmt_mode *cp = data;
4298 struct pending_cmd *cmd;
4299 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004300 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004301 int err;
4302
4303 BT_DBG("request for %s", hdev->name);
4304
Johan Hedberge6fe7982013-10-02 15:45:22 +03004305 status = mgmt_le_support(hdev);
4306 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004307 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004308 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004309
4310 if (cp->val != 0x00 && cp->val != 0x01)
4311 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4312 MGMT_STATUS_INVALID_PARAMS);
4313
4314 hci_dev_lock(hdev);
4315
4316 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004317 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004318
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004319 /* The following conditions are ones which mean that we should
4320 * not do any HCI communication but directly send a mgmt
4321 * response to user space (after toggling the flag if
4322 * necessary).
4323 */
4324 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004325 hci_conn_num(hdev, LE_LINK) > 0 ||
4326 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4327 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004328 bool changed = false;
4329
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004330 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4331 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004332 changed = true;
4333 }
4334
4335 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4336 if (err < 0)
4337 goto unlock;
4338
4339 if (changed)
4340 err = new_settings(hdev, sk);
4341
4342 goto unlock;
4343 }
4344
4345 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4346 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4347 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4348 MGMT_STATUS_BUSY);
4349 goto unlock;
4350 }
4351
4352 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4353 if (!cmd) {
4354 err = -ENOMEM;
4355 goto unlock;
4356 }
4357
4358 hci_req_init(&req, hdev);
4359
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004360 if (val)
4361 enable_advertising(&req);
4362 else
4363 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004364
4365 err = hci_req_run(&req, set_advertising_complete);
4366 if (err < 0)
4367 mgmt_pending_remove(cmd);
4368
4369unlock:
4370 hci_dev_unlock(hdev);
4371 return err;
4372}
4373
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004374static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4375 void *data, u16 len)
4376{
4377 struct mgmt_cp_set_static_address *cp = data;
4378 int err;
4379
4380 BT_DBG("%s", hdev->name);
4381
Marcel Holtmann62af4442013-10-02 22:10:32 -07004382 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004383 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004384 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004385
4386 if (hdev_is_powered(hdev))
4387 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4388 MGMT_STATUS_REJECTED);
4389
4390 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4391 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4392 return cmd_status(sk, hdev->id,
4393 MGMT_OP_SET_STATIC_ADDRESS,
4394 MGMT_STATUS_INVALID_PARAMS);
4395
4396 /* Two most significant bits shall be set */
4397 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4398 return cmd_status(sk, hdev->id,
4399 MGMT_OP_SET_STATIC_ADDRESS,
4400 MGMT_STATUS_INVALID_PARAMS);
4401 }
4402
4403 hci_dev_lock(hdev);
4404
4405 bacpy(&hdev->static_addr, &cp->bdaddr);
4406
4407 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4408
4409 hci_dev_unlock(hdev);
4410
4411 return err;
4412}
4413
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004414static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4415 void *data, u16 len)
4416{
4417 struct mgmt_cp_set_scan_params *cp = data;
4418 __u16 interval, window;
4419 int err;
4420
4421 BT_DBG("%s", hdev->name);
4422
4423 if (!lmp_le_capable(hdev))
4424 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4425 MGMT_STATUS_NOT_SUPPORTED);
4426
4427 interval = __le16_to_cpu(cp->interval);
4428
4429 if (interval < 0x0004 || interval > 0x4000)
4430 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4431 MGMT_STATUS_INVALID_PARAMS);
4432
4433 window = __le16_to_cpu(cp->window);
4434
4435 if (window < 0x0004 || window > 0x4000)
4436 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4437 MGMT_STATUS_INVALID_PARAMS);
4438
Marcel Holtmann899e1072013-10-14 09:55:32 -07004439 if (window > interval)
4440 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4441 MGMT_STATUS_INVALID_PARAMS);
4442
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004443 hci_dev_lock(hdev);
4444
4445 hdev->le_scan_interval = interval;
4446 hdev->le_scan_window = window;
4447
4448 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4449
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004450 /* If background scan is running, restart it so new parameters are
4451 * loaded.
4452 */
4453 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4454 hdev->discovery.state == DISCOVERY_STOPPED) {
4455 struct hci_request req;
4456
4457 hci_req_init(&req, hdev);
4458
4459 hci_req_add_le_scan_disable(&req);
4460 hci_req_add_le_passive_scan(&req);
4461
4462 hci_req_run(&req, NULL);
4463 }
4464
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004465 hci_dev_unlock(hdev);
4466
4467 return err;
4468}
4469
Johan Hedberg33e38b32013-03-15 17:07:05 -05004470static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4471{
4472 struct pending_cmd *cmd;
4473
4474 BT_DBG("status 0x%02x", status);
4475
4476 hci_dev_lock(hdev);
4477
4478 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4479 if (!cmd)
4480 goto unlock;
4481
4482 if (status) {
4483 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4484 mgmt_status(status));
4485 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004486 struct mgmt_mode *cp = cmd->param;
4487
4488 if (cp->val)
4489 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4490 else
4491 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4492
Johan Hedberg33e38b32013-03-15 17:07:05 -05004493 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4494 new_settings(hdev, cmd->sk);
4495 }
4496
4497 mgmt_pending_remove(cmd);
4498
4499unlock:
4500 hci_dev_unlock(hdev);
4501}
4502
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004503static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004504 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004505{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004506 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004507 struct pending_cmd *cmd;
4508 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004509 int err;
4510
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004511 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004512
Johan Hedberg56f87902013-10-02 13:43:13 +03004513 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4514 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004515 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4516 MGMT_STATUS_NOT_SUPPORTED);
4517
Johan Hedberga7e80f22013-01-09 16:05:19 +02004518 if (cp->val != 0x00 && cp->val != 0x01)
4519 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4520 MGMT_STATUS_INVALID_PARAMS);
4521
Johan Hedberg5400c042012-02-21 16:40:33 +02004522 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004523 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004524 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004525
4526 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004527 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004528 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004529
4530 hci_dev_lock(hdev);
4531
Johan Hedberg05cbf292013-03-15 17:07:07 -05004532 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4533 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4534 MGMT_STATUS_BUSY);
4535 goto unlock;
4536 }
4537
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004538 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4539 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4540 hdev);
4541 goto unlock;
4542 }
4543
Johan Hedberg33e38b32013-03-15 17:07:05 -05004544 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4545 data, len);
4546 if (!cmd) {
4547 err = -ENOMEM;
4548 goto unlock;
4549 }
4550
4551 hci_req_init(&req, hdev);
4552
Johan Hedberg406d7802013-03-15 17:07:09 -05004553 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004554
4555 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004556 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004557 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004558 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004559 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004560 }
4561
Johan Hedberg33e38b32013-03-15 17:07:05 -05004562unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004563 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004564
Antti Julkuf6422ec2011-06-22 13:11:56 +03004565 return err;
4566}
4567
Johan Hedberg0663ca22013-10-02 13:43:14 +03004568static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4569{
4570 struct pending_cmd *cmd;
4571
4572 BT_DBG("status 0x%02x", status);
4573
4574 hci_dev_lock(hdev);
4575
4576 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4577 if (!cmd)
4578 goto unlock;
4579
4580 if (status) {
4581 u8 mgmt_err = mgmt_status(status);
4582
4583 /* We need to restore the flag if related HCI commands
4584 * failed.
4585 */
4586 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4587
4588 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4589 } else {
4590 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4591 new_settings(hdev, cmd->sk);
4592 }
4593
4594 mgmt_pending_remove(cmd);
4595
4596unlock:
4597 hci_dev_unlock(hdev);
4598}
4599
4600static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4601{
4602 struct mgmt_mode *cp = data;
4603 struct pending_cmd *cmd;
4604 struct hci_request req;
4605 int err;
4606
4607 BT_DBG("request for %s", hdev->name);
4608
4609 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4610 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4611 MGMT_STATUS_NOT_SUPPORTED);
4612
4613 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4614 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4615 MGMT_STATUS_REJECTED);
4616
4617 if (cp->val != 0x00 && cp->val != 0x01)
4618 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4619 MGMT_STATUS_INVALID_PARAMS);
4620
4621 hci_dev_lock(hdev);
4622
4623 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4624 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4625 goto unlock;
4626 }
4627
4628 if (!hdev_is_powered(hdev)) {
4629 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004630 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4631 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4632 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4633 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4634 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4635 }
4636
4637 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4638
4639 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4640 if (err < 0)
4641 goto unlock;
4642
4643 err = new_settings(hdev, sk);
4644 goto unlock;
4645 }
4646
4647 /* Reject disabling when powered on */
4648 if (!cp->val) {
4649 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4650 MGMT_STATUS_REJECTED);
4651 goto unlock;
4652 }
4653
4654 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4655 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4656 MGMT_STATUS_BUSY);
4657 goto unlock;
4658 }
4659
4660 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4661 if (!cmd) {
4662 err = -ENOMEM;
4663 goto unlock;
4664 }
4665
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004666 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004667 * generates the correct flags.
4668 */
4669 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4670
4671 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004672
Johan Hedberg432df052014-08-01 11:13:31 +03004673 write_fast_connectable(&req, false);
4674 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004675
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004676 /* Since only the advertising data flags will change, there
4677 * is no need to update the scan response data.
4678 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004679 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004680
Johan Hedberg0663ca22013-10-02 13:43:14 +03004681 err = hci_req_run(&req, set_bredr_complete);
4682 if (err < 0)
4683 mgmt_pending_remove(cmd);
4684
4685unlock:
4686 hci_dev_unlock(hdev);
4687 return err;
4688}
4689
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004690static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4691 void *data, u16 len)
4692{
4693 struct mgmt_mode *cp = data;
4694 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004695 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004696 int err;
4697
4698 BT_DBG("request for %s", hdev->name);
4699
Johan Hedberga3209692014-05-26 11:23:35 +03004700 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4701 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004702 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4703 MGMT_STATUS_NOT_SUPPORTED);
4704
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004705 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004706 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4707 MGMT_STATUS_INVALID_PARAMS);
4708
4709 hci_dev_lock(hdev);
4710
Johan Hedberga3209692014-05-26 11:23:35 +03004711 if (!hdev_is_powered(hdev) ||
4712 (!lmp_sc_capable(hdev) &&
4713 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4714 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004715 bool changed;
4716
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004717 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004718 changed = !test_and_set_bit(HCI_SC_ENABLED,
4719 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004720 if (cp->val == 0x02)
4721 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4722 else
4723 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4724 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004725 changed = test_and_clear_bit(HCI_SC_ENABLED,
4726 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004727 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4728 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004729
4730 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4731 if (err < 0)
4732 goto failed;
4733
4734 if (changed)
4735 err = new_settings(hdev, sk);
4736
4737 goto failed;
4738 }
4739
4740 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4741 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4742 MGMT_STATUS_BUSY);
4743 goto failed;
4744 }
4745
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004746 val = !!cp->val;
4747
4748 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4749 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004750 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4751 goto failed;
4752 }
4753
4754 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4755 if (!cmd) {
4756 err = -ENOMEM;
4757 goto failed;
4758 }
4759
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004760 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004761 if (err < 0) {
4762 mgmt_pending_remove(cmd);
4763 goto failed;
4764 }
4765
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004766 if (cp->val == 0x02)
4767 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4768 else
4769 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4770
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004771failed:
4772 hci_dev_unlock(hdev);
4773 return err;
4774}
4775
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004776static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4777 void *data, u16 len)
4778{
4779 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004780 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004781 int err;
4782
4783 BT_DBG("request for %s", hdev->name);
4784
Johan Hedbergb97109792014-06-24 14:00:28 +03004785 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004786 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4787 MGMT_STATUS_INVALID_PARAMS);
4788
4789 hci_dev_lock(hdev);
4790
4791 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004792 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4793 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004794 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004795 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4796 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004797
Johan Hedbergb97109792014-06-24 14:00:28 +03004798 if (cp->val == 0x02)
4799 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4800 &hdev->dev_flags);
4801 else
4802 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4803 &hdev->dev_flags);
4804
4805 if (hdev_is_powered(hdev) && use_changed &&
4806 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4807 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4808 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4809 sizeof(mode), &mode);
4810 }
4811
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004812 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4813 if (err < 0)
4814 goto unlock;
4815
4816 if (changed)
4817 err = new_settings(hdev, sk);
4818
4819unlock:
4820 hci_dev_unlock(hdev);
4821 return err;
4822}
4823
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004824static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4825 u16 len)
4826{
4827 struct mgmt_cp_set_privacy *cp = cp_data;
4828 bool changed;
4829 int err;
4830
4831 BT_DBG("request for %s", hdev->name);
4832
4833 if (!lmp_le_capable(hdev))
4834 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4835 MGMT_STATUS_NOT_SUPPORTED);
4836
4837 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4838 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4839 MGMT_STATUS_INVALID_PARAMS);
4840
4841 if (hdev_is_powered(hdev))
4842 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4843 MGMT_STATUS_REJECTED);
4844
4845 hci_dev_lock(hdev);
4846
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004847 /* If user space supports this command it is also expected to
4848 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4849 */
4850 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4851
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004852 if (cp->privacy) {
4853 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4854 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4855 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4856 } else {
4857 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4858 memset(hdev->irk, 0, sizeof(hdev->irk));
4859 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4860 }
4861
4862 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4863 if (err < 0)
4864 goto unlock;
4865
4866 if (changed)
4867 err = new_settings(hdev, sk);
4868
4869unlock:
4870 hci_dev_unlock(hdev);
4871 return err;
4872}
4873
Johan Hedberg41edf162014-02-18 10:19:35 +02004874static bool irk_is_valid(struct mgmt_irk_info *irk)
4875{
4876 switch (irk->addr.type) {
4877 case BDADDR_LE_PUBLIC:
4878 return true;
4879
4880 case BDADDR_LE_RANDOM:
4881 /* Two most significant bits shall be set */
4882 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4883 return false;
4884 return true;
4885 }
4886
4887 return false;
4888}
4889
4890static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4891 u16 len)
4892{
4893 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004894 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4895 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004896 u16 irk_count, expected_len;
4897 int i, err;
4898
4899 BT_DBG("request for %s", hdev->name);
4900
4901 if (!lmp_le_capable(hdev))
4902 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4903 MGMT_STATUS_NOT_SUPPORTED);
4904
4905 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004906 if (irk_count > max_irk_count) {
4907 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4908 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4909 MGMT_STATUS_INVALID_PARAMS);
4910 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004911
4912 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4913 if (expected_len != len) {
4914 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004915 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004916 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4917 MGMT_STATUS_INVALID_PARAMS);
4918 }
4919
4920 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4921
4922 for (i = 0; i < irk_count; i++) {
4923 struct mgmt_irk_info *key = &cp->irks[i];
4924
4925 if (!irk_is_valid(key))
4926 return cmd_status(sk, hdev->id,
4927 MGMT_OP_LOAD_IRKS,
4928 MGMT_STATUS_INVALID_PARAMS);
4929 }
4930
4931 hci_dev_lock(hdev);
4932
4933 hci_smp_irks_clear(hdev);
4934
4935 for (i = 0; i < irk_count; i++) {
4936 struct mgmt_irk_info *irk = &cp->irks[i];
4937 u8 addr_type;
4938
4939 if (irk->addr.type == BDADDR_LE_PUBLIC)
4940 addr_type = ADDR_LE_DEV_PUBLIC;
4941 else
4942 addr_type = ADDR_LE_DEV_RANDOM;
4943
4944 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4945 BDADDR_ANY);
4946 }
4947
4948 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4949
4950 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4951
4952 hci_dev_unlock(hdev);
4953
4954 return err;
4955}
4956
Johan Hedberg3f706b72013-01-20 14:27:16 +02004957static bool ltk_is_valid(struct mgmt_ltk_info *key)
4958{
4959 if (key->master != 0x00 && key->master != 0x01)
4960 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004961
4962 switch (key->addr.type) {
4963 case BDADDR_LE_PUBLIC:
4964 return true;
4965
4966 case BDADDR_LE_RANDOM:
4967 /* Two most significant bits shall be set */
4968 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4969 return false;
4970 return true;
4971 }
4972
4973 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004974}
4975
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004976static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004977 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004978{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004979 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004980 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4981 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004982 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004983 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004984
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004985 BT_DBG("request for %s", hdev->name);
4986
4987 if (!lmp_le_capable(hdev))
4988 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4989 MGMT_STATUS_NOT_SUPPORTED);
4990
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004991 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004992 if (key_count > max_key_count) {
4993 BT_ERR("load_ltks: too big key_count value %u", key_count);
4994 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4995 MGMT_STATUS_INVALID_PARAMS);
4996 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004997
4998 expected_len = sizeof(*cp) + key_count *
4999 sizeof(struct mgmt_ltk_info);
5000 if (expected_len != len) {
5001 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005002 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005003 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005004 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005005 }
5006
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005007 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005008
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005009 for (i = 0; i < key_count; i++) {
5010 struct mgmt_ltk_info *key = &cp->keys[i];
5011
Johan Hedberg3f706b72013-01-20 14:27:16 +02005012 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005013 return cmd_status(sk, hdev->id,
5014 MGMT_OP_LOAD_LONG_TERM_KEYS,
5015 MGMT_STATUS_INVALID_PARAMS);
5016 }
5017
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005018 hci_dev_lock(hdev);
5019
5020 hci_smp_ltks_clear(hdev);
5021
5022 for (i = 0; i < key_count; i++) {
5023 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005024 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005025
5026 if (key->addr.type == BDADDR_LE_PUBLIC)
5027 addr_type = ADDR_LE_DEV_PUBLIC;
5028 else
5029 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005030
Johan Hedberg61b43352014-05-29 19:36:53 +03005031 switch (key->type) {
5032 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005033 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005034 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005035 break;
5036 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005037 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005038 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005039 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005040 case MGMT_LTK_P256_UNAUTH:
5041 authenticated = 0x00;
5042 type = SMP_LTK_P256;
5043 break;
5044 case MGMT_LTK_P256_AUTH:
5045 authenticated = 0x01;
5046 type = SMP_LTK_P256;
5047 break;
5048 case MGMT_LTK_P256_DEBUG:
5049 authenticated = 0x00;
5050 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005051 default:
5052 continue;
5053 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005054
Johan Hedberg35d70272014-02-19 14:57:47 +02005055 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005056 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005057 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005058 }
5059
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005060 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5061 NULL, 0);
5062
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005063 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005064
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005065 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005066}
5067
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005068struct cmd_conn_lookup {
5069 struct hci_conn *conn;
5070 bool valid_tx_power;
5071 u8 mgmt_status;
5072};
5073
5074static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
5075{
5076 struct cmd_conn_lookup *match = data;
5077 struct mgmt_cp_get_conn_info *cp;
5078 struct mgmt_rp_get_conn_info rp;
5079 struct hci_conn *conn = cmd->user_data;
5080
5081 if (conn != match->conn)
5082 return;
5083
5084 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
5085
5086 memset(&rp, 0, sizeof(rp));
5087 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5088 rp.addr.type = cp->addr.type;
5089
5090 if (!match->mgmt_status) {
5091 rp.rssi = conn->rssi;
5092
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005093 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005094 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005095 rp.max_tx_power = conn->max_tx_power;
5096 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005097 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005098 rp.max_tx_power = HCI_TX_POWER_INVALID;
5099 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005100 }
5101
5102 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5103 match->mgmt_status, &rp, sizeof(rp));
5104
5105 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005106 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005107
5108 mgmt_pending_remove(cmd);
5109}
5110
5111static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5112{
5113 struct hci_cp_read_rssi *cp;
5114 struct hci_conn *conn;
5115 struct cmd_conn_lookup match;
5116 u16 handle;
5117
5118 BT_DBG("status 0x%02x", status);
5119
5120 hci_dev_lock(hdev);
5121
5122 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005123 * otherwise we assume it's not valid. At the moment we assume that
5124 * either both or none of current and max values are valid to keep code
5125 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005126 */
5127 match.valid_tx_power = !status;
5128
5129 /* Commands sent in request are either Read RSSI or Read Transmit Power
5130 * Level so we check which one was last sent to retrieve connection
5131 * handle. Both commands have handle as first parameter so it's safe to
5132 * cast data on the same command struct.
5133 *
5134 * First command sent is always Read RSSI and we fail only if it fails.
5135 * In other case we simply override error to indicate success as we
5136 * already remembered if TX power value is actually valid.
5137 */
5138 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5139 if (!cp) {
5140 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5141 status = 0;
5142 }
5143
5144 if (!cp) {
5145 BT_ERR("invalid sent_cmd in response");
5146 goto unlock;
5147 }
5148
5149 handle = __le16_to_cpu(cp->handle);
5150 conn = hci_conn_hash_lookup_handle(hdev, handle);
5151 if (!conn) {
5152 BT_ERR("unknown handle (%d) in response", handle);
5153 goto unlock;
5154 }
5155
5156 match.conn = conn;
5157 match.mgmt_status = mgmt_status(status);
5158
5159 /* Cache refresh is complete, now reply for mgmt request for given
5160 * connection only.
5161 */
5162 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5163 get_conn_info_complete, &match);
5164
5165unlock:
5166 hci_dev_unlock(hdev);
5167}
5168
5169static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5170 u16 len)
5171{
5172 struct mgmt_cp_get_conn_info *cp = data;
5173 struct mgmt_rp_get_conn_info rp;
5174 struct hci_conn *conn;
5175 unsigned long conn_info_age;
5176 int err = 0;
5177
5178 BT_DBG("%s", hdev->name);
5179
5180 memset(&rp, 0, sizeof(rp));
5181 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5182 rp.addr.type = cp->addr.type;
5183
5184 if (!bdaddr_type_is_valid(cp->addr.type))
5185 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5186 MGMT_STATUS_INVALID_PARAMS,
5187 &rp, sizeof(rp));
5188
5189 hci_dev_lock(hdev);
5190
5191 if (!hdev_is_powered(hdev)) {
5192 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5193 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5194 goto unlock;
5195 }
5196
5197 if (cp->addr.type == BDADDR_BREDR)
5198 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5199 &cp->addr.bdaddr);
5200 else
5201 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5202
5203 if (!conn || conn->state != BT_CONNECTED) {
5204 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5205 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5206 goto unlock;
5207 }
5208
5209 /* To avoid client trying to guess when to poll again for information we
5210 * calculate conn info age as random value between min/max set in hdev.
5211 */
5212 conn_info_age = hdev->conn_info_min_age +
5213 prandom_u32_max(hdev->conn_info_max_age -
5214 hdev->conn_info_min_age);
5215
5216 /* Query controller to refresh cached values if they are too old or were
5217 * never read.
5218 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005219 if (time_after(jiffies, conn->conn_info_timestamp +
5220 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005221 !conn->conn_info_timestamp) {
5222 struct hci_request req;
5223 struct hci_cp_read_tx_power req_txp_cp;
5224 struct hci_cp_read_rssi req_rssi_cp;
5225 struct pending_cmd *cmd;
5226
5227 hci_req_init(&req, hdev);
5228 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5229 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5230 &req_rssi_cp);
5231
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005232 /* For LE links TX power does not change thus we don't need to
5233 * query for it once value is known.
5234 */
5235 if (!bdaddr_type_is_le(cp->addr.type) ||
5236 conn->tx_power == HCI_TX_POWER_INVALID) {
5237 req_txp_cp.handle = cpu_to_le16(conn->handle);
5238 req_txp_cp.type = 0x00;
5239 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5240 sizeof(req_txp_cp), &req_txp_cp);
5241 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005242
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005243 /* Max TX power needs to be read only once per connection */
5244 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5245 req_txp_cp.handle = cpu_to_le16(conn->handle);
5246 req_txp_cp.type = 0x01;
5247 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5248 sizeof(req_txp_cp), &req_txp_cp);
5249 }
5250
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005251 err = hci_req_run(&req, conn_info_refresh_complete);
5252 if (err < 0)
5253 goto unlock;
5254
5255 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5256 data, len);
5257 if (!cmd) {
5258 err = -ENOMEM;
5259 goto unlock;
5260 }
5261
5262 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005263 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005264
5265 conn->conn_info_timestamp = jiffies;
5266 } else {
5267 /* Cache is valid, just reply with values cached in hci_conn */
5268 rp.rssi = conn->rssi;
5269 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005270 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005271
5272 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5273 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5274 }
5275
5276unlock:
5277 hci_dev_unlock(hdev);
5278 return err;
5279}
5280
Johan Hedberg95868422014-06-28 17:54:07 +03005281static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5282{
5283 struct mgmt_cp_get_clock_info *cp;
5284 struct mgmt_rp_get_clock_info rp;
5285 struct hci_cp_read_clock *hci_cp;
5286 struct pending_cmd *cmd;
5287 struct hci_conn *conn;
5288
5289 BT_DBG("%s status %u", hdev->name, status);
5290
5291 hci_dev_lock(hdev);
5292
5293 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5294 if (!hci_cp)
5295 goto unlock;
5296
5297 if (hci_cp->which) {
5298 u16 handle = __le16_to_cpu(hci_cp->handle);
5299 conn = hci_conn_hash_lookup_handle(hdev, handle);
5300 } else {
5301 conn = NULL;
5302 }
5303
5304 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5305 if (!cmd)
5306 goto unlock;
5307
5308 cp = cmd->param;
5309
5310 memset(&rp, 0, sizeof(rp));
5311 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5312
5313 if (status)
5314 goto send_rsp;
5315
5316 rp.local_clock = cpu_to_le32(hdev->clock);
5317
5318 if (conn) {
5319 rp.piconet_clock = cpu_to_le32(conn->clock);
5320 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5321 }
5322
5323send_rsp:
5324 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5325 &rp, sizeof(rp));
5326 mgmt_pending_remove(cmd);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005327 if (conn) {
Johan Hedberg95868422014-06-28 17:54:07 +03005328 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005329 hci_conn_put(conn);
5330 }
Johan Hedberg95868422014-06-28 17:54:07 +03005331
5332unlock:
5333 hci_dev_unlock(hdev);
5334}
5335
5336static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5337 u16 len)
5338{
5339 struct mgmt_cp_get_clock_info *cp = data;
5340 struct mgmt_rp_get_clock_info rp;
5341 struct hci_cp_read_clock hci_cp;
5342 struct pending_cmd *cmd;
5343 struct hci_request req;
5344 struct hci_conn *conn;
5345 int err;
5346
5347 BT_DBG("%s", hdev->name);
5348
5349 memset(&rp, 0, sizeof(rp));
5350 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5351 rp.addr.type = cp->addr.type;
5352
5353 if (cp->addr.type != BDADDR_BREDR)
5354 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5355 MGMT_STATUS_INVALID_PARAMS,
5356 &rp, sizeof(rp));
5357
5358 hci_dev_lock(hdev);
5359
5360 if (!hdev_is_powered(hdev)) {
5361 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5362 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5363 goto unlock;
5364 }
5365
5366 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5367 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5368 &cp->addr.bdaddr);
5369 if (!conn || conn->state != BT_CONNECTED) {
5370 err = cmd_complete(sk, hdev->id,
5371 MGMT_OP_GET_CLOCK_INFO,
5372 MGMT_STATUS_NOT_CONNECTED,
5373 &rp, sizeof(rp));
5374 goto unlock;
5375 }
5376 } else {
5377 conn = NULL;
5378 }
5379
5380 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5381 if (!cmd) {
5382 err = -ENOMEM;
5383 goto unlock;
5384 }
5385
5386 hci_req_init(&req, hdev);
5387
5388 memset(&hci_cp, 0, sizeof(hci_cp));
5389 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5390
5391 if (conn) {
5392 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005393 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005394
5395 hci_cp.handle = cpu_to_le16(conn->handle);
5396 hci_cp.which = 0x01; /* Piconet clock */
5397 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5398 }
5399
5400 err = hci_req_run(&req, get_clock_info_complete);
5401 if (err < 0)
5402 mgmt_pending_remove(cmd);
5403
5404unlock:
5405 hci_dev_unlock(hdev);
5406 return err;
5407}
5408
Marcel Holtmann8afef092014-06-29 22:28:34 +02005409static void device_added(struct sock *sk, struct hci_dev *hdev,
5410 bdaddr_t *bdaddr, u8 type, u8 action)
5411{
5412 struct mgmt_ev_device_added ev;
5413
5414 bacpy(&ev.addr.bdaddr, bdaddr);
5415 ev.addr.type = type;
5416 ev.action = action;
5417
5418 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5419}
5420
Marcel Holtmann2faade52014-06-29 19:44:03 +02005421static int add_device(struct sock *sk, struct hci_dev *hdev,
5422 void *data, u16 len)
5423{
5424 struct mgmt_cp_add_device *cp = data;
5425 u8 auto_conn, addr_type;
5426 int err;
5427
5428 BT_DBG("%s", hdev->name);
5429
Johan Hedberg66593582014-07-09 12:59:14 +03005430 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005431 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5432 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5433 MGMT_STATUS_INVALID_PARAMS,
5434 &cp->addr, sizeof(cp->addr));
5435
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005436 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005437 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5438 MGMT_STATUS_INVALID_PARAMS,
5439 &cp->addr, sizeof(cp->addr));
5440
5441 hci_dev_lock(hdev);
5442
Johan Hedberg66593582014-07-09 12:59:14 +03005443 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005444 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005445 if (cp->action != 0x01) {
5446 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5447 MGMT_STATUS_INVALID_PARAMS,
5448 &cp->addr, sizeof(cp->addr));
5449 goto unlock;
5450 }
5451
5452 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5453 cp->addr.type);
5454 if (err)
5455 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005456
Johan Hedberg432df052014-08-01 11:13:31 +03005457 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005458
Johan Hedberg66593582014-07-09 12:59:14 +03005459 goto added;
5460 }
5461
Marcel Holtmann2faade52014-06-29 19:44:03 +02005462 if (cp->addr.type == BDADDR_LE_PUBLIC)
5463 addr_type = ADDR_LE_DEV_PUBLIC;
5464 else
5465 addr_type = ADDR_LE_DEV_RANDOM;
5466
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005467 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005468 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005469 else if (cp->action == 0x01)
5470 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005471 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005472 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005473
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005474 /* If the connection parameters don't exist for this device,
5475 * they will be created and configured with defaults.
5476 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005477 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5478 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005479 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5480 MGMT_STATUS_FAILED,
5481 &cp->addr, sizeof(cp->addr));
5482 goto unlock;
5483 }
5484
Johan Hedberg66593582014-07-09 12:59:14 +03005485added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005486 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5487
Marcel Holtmann2faade52014-06-29 19:44:03 +02005488 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5489 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5490
5491unlock:
5492 hci_dev_unlock(hdev);
5493 return err;
5494}
5495
Marcel Holtmann8afef092014-06-29 22:28:34 +02005496static void device_removed(struct sock *sk, struct hci_dev *hdev,
5497 bdaddr_t *bdaddr, u8 type)
5498{
5499 struct mgmt_ev_device_removed ev;
5500
5501 bacpy(&ev.addr.bdaddr, bdaddr);
5502 ev.addr.type = type;
5503
5504 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5505}
5506
Marcel Holtmann2faade52014-06-29 19:44:03 +02005507static int remove_device(struct sock *sk, struct hci_dev *hdev,
5508 void *data, u16 len)
5509{
5510 struct mgmt_cp_remove_device *cp = data;
5511 int err;
5512
5513 BT_DBG("%s", hdev->name);
5514
5515 hci_dev_lock(hdev);
5516
5517 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005518 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005519 u8 addr_type;
5520
Johan Hedberg66593582014-07-09 12:59:14 +03005521 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005522 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5523 MGMT_STATUS_INVALID_PARAMS,
5524 &cp->addr, sizeof(cp->addr));
5525 goto unlock;
5526 }
5527
Johan Hedberg66593582014-07-09 12:59:14 +03005528 if (cp->addr.type == BDADDR_BREDR) {
5529 err = hci_bdaddr_list_del(&hdev->whitelist,
5530 &cp->addr.bdaddr,
5531 cp->addr.type);
5532 if (err) {
5533 err = cmd_complete(sk, hdev->id,
5534 MGMT_OP_REMOVE_DEVICE,
5535 MGMT_STATUS_INVALID_PARAMS,
5536 &cp->addr, sizeof(cp->addr));
5537 goto unlock;
5538 }
5539
Johan Hedberg432df052014-08-01 11:13:31 +03005540 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005541
Johan Hedberg66593582014-07-09 12:59:14 +03005542 device_removed(sk, hdev, &cp->addr.bdaddr,
5543 cp->addr.type);
5544 goto complete;
5545 }
5546
Marcel Holtmann2faade52014-06-29 19:44:03 +02005547 if (cp->addr.type == BDADDR_LE_PUBLIC)
5548 addr_type = ADDR_LE_DEV_PUBLIC;
5549 else
5550 addr_type = ADDR_LE_DEV_RANDOM;
5551
Johan Hedbergc71593d2014-07-02 17:37:28 +03005552 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5553 addr_type);
5554 if (!params) {
5555 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5556 MGMT_STATUS_INVALID_PARAMS,
5557 &cp->addr, sizeof(cp->addr));
5558 goto unlock;
5559 }
5560
5561 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5562 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5563 MGMT_STATUS_INVALID_PARAMS,
5564 &cp->addr, sizeof(cp->addr));
5565 goto unlock;
5566 }
5567
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005568 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005569 list_del(&params->list);
5570 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005571 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005572
5573 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005574 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005575 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005576 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005577
Marcel Holtmann2faade52014-06-29 19:44:03 +02005578 if (cp->addr.type) {
5579 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5580 MGMT_STATUS_INVALID_PARAMS,
5581 &cp->addr, sizeof(cp->addr));
5582 goto unlock;
5583 }
5584
Johan Hedberg66593582014-07-09 12:59:14 +03005585 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5586 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5587 list_del(&b->list);
5588 kfree(b);
5589 }
5590
Johan Hedberg432df052014-08-01 11:13:31 +03005591 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005592
Johan Hedberg19de0822014-07-06 13:06:51 +03005593 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5594 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5595 continue;
5596 device_removed(sk, hdev, &p->addr, p->addr_type);
5597 list_del(&p->action);
5598 list_del(&p->list);
5599 kfree(p);
5600 }
5601
5602 BT_DBG("All LE connection parameters were removed");
5603
5604 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005605 }
5606
Johan Hedberg66593582014-07-09 12:59:14 +03005607complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005608 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5609 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5610
5611unlock:
5612 hci_dev_unlock(hdev);
5613 return err;
5614}
5615
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005616static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5617 u16 len)
5618{
5619 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005620 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5621 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005622 u16 param_count, expected_len;
5623 int i;
5624
5625 if (!lmp_le_capable(hdev))
5626 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5627 MGMT_STATUS_NOT_SUPPORTED);
5628
5629 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005630 if (param_count > max_param_count) {
5631 BT_ERR("load_conn_param: too big param_count value %u",
5632 param_count);
5633 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5634 MGMT_STATUS_INVALID_PARAMS);
5635 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005636
5637 expected_len = sizeof(*cp) + param_count *
5638 sizeof(struct mgmt_conn_param);
5639 if (expected_len != len) {
5640 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5641 expected_len, len);
5642 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5643 MGMT_STATUS_INVALID_PARAMS);
5644 }
5645
5646 BT_DBG("%s param_count %u", hdev->name, param_count);
5647
5648 hci_dev_lock(hdev);
5649
5650 hci_conn_params_clear_disabled(hdev);
5651
5652 for (i = 0; i < param_count; i++) {
5653 struct mgmt_conn_param *param = &cp->params[i];
5654 struct hci_conn_params *hci_param;
5655 u16 min, max, latency, timeout;
5656 u8 addr_type;
5657
5658 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5659 param->addr.type);
5660
5661 if (param->addr.type == BDADDR_LE_PUBLIC) {
5662 addr_type = ADDR_LE_DEV_PUBLIC;
5663 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5664 addr_type = ADDR_LE_DEV_RANDOM;
5665 } else {
5666 BT_ERR("Ignoring invalid connection parameters");
5667 continue;
5668 }
5669
5670 min = le16_to_cpu(param->min_interval);
5671 max = le16_to_cpu(param->max_interval);
5672 latency = le16_to_cpu(param->latency);
5673 timeout = le16_to_cpu(param->timeout);
5674
5675 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5676 min, max, latency, timeout);
5677
5678 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5679 BT_ERR("Ignoring invalid connection parameters");
5680 continue;
5681 }
5682
5683 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5684 addr_type);
5685 if (!hci_param) {
5686 BT_ERR("Failed to add connection parameters");
5687 continue;
5688 }
5689
5690 hci_param->conn_min_interval = min;
5691 hci_param->conn_max_interval = max;
5692 hci_param->conn_latency = latency;
5693 hci_param->supervision_timeout = timeout;
5694 }
5695
5696 hci_dev_unlock(hdev);
5697
5698 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5699}
5700
Marcel Holtmanndbece372014-07-04 18:11:55 +02005701static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5702 void *data, u16 len)
5703{
5704 struct mgmt_cp_set_external_config *cp = data;
5705 bool changed;
5706 int err;
5707
5708 BT_DBG("%s", hdev->name);
5709
5710 if (hdev_is_powered(hdev))
5711 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5712 MGMT_STATUS_REJECTED);
5713
5714 if (cp->config != 0x00 && cp->config != 0x01)
5715 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5716 MGMT_STATUS_INVALID_PARAMS);
5717
5718 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5719 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5720 MGMT_STATUS_NOT_SUPPORTED);
5721
5722 hci_dev_lock(hdev);
5723
5724 if (cp->config)
5725 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5726 &hdev->dev_flags);
5727 else
5728 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5729 &hdev->dev_flags);
5730
5731 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5732 if (err < 0)
5733 goto unlock;
5734
5735 if (!changed)
5736 goto unlock;
5737
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005738 err = new_options(hdev, sk);
5739
Marcel Holtmanndbece372014-07-04 18:11:55 +02005740 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5741 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005742
5743 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5744 set_bit(HCI_CONFIG, &hdev->dev_flags);
5745 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5746
5747 queue_work(hdev->req_workqueue, &hdev->power_on);
5748 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005749 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005750 mgmt_index_added(hdev);
5751 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005752 }
5753
5754unlock:
5755 hci_dev_unlock(hdev);
5756 return err;
5757}
5758
Marcel Holtmann9713c172014-07-06 12:11:15 +02005759static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5760 void *data, u16 len)
5761{
5762 struct mgmt_cp_set_public_address *cp = data;
5763 bool changed;
5764 int err;
5765
5766 BT_DBG("%s", hdev->name);
5767
5768 if (hdev_is_powered(hdev))
5769 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5770 MGMT_STATUS_REJECTED);
5771
5772 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5773 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5774 MGMT_STATUS_INVALID_PARAMS);
5775
5776 if (!hdev->set_bdaddr)
5777 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5778 MGMT_STATUS_NOT_SUPPORTED);
5779
5780 hci_dev_lock(hdev);
5781
5782 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5783 bacpy(&hdev->public_addr, &cp->bdaddr);
5784
5785 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5786 if (err < 0)
5787 goto unlock;
5788
5789 if (!changed)
5790 goto unlock;
5791
5792 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5793 err = new_options(hdev, sk);
5794
5795 if (is_configured(hdev)) {
5796 mgmt_index_removed(hdev);
5797
5798 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5799
5800 set_bit(HCI_CONFIG, &hdev->dev_flags);
5801 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5802
5803 queue_work(hdev->req_workqueue, &hdev->power_on);
5804 }
5805
5806unlock:
5807 hci_dev_unlock(hdev);
5808 return err;
5809}
5810
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005811static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005812 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5813 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005814 bool var_len;
5815 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005816} mgmt_handlers[] = {
5817 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005818 { read_version, false, MGMT_READ_VERSION_SIZE },
5819 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5820 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5821 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5822 { set_powered, false, MGMT_SETTING_SIZE },
5823 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5824 { set_connectable, false, MGMT_SETTING_SIZE },
5825 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005826 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005827 { set_link_security, false, MGMT_SETTING_SIZE },
5828 { set_ssp, false, MGMT_SETTING_SIZE },
5829 { set_hs, false, MGMT_SETTING_SIZE },
5830 { set_le, false, MGMT_SETTING_SIZE },
5831 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5832 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5833 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5834 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5835 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5836 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5837 { disconnect, false, MGMT_DISCONNECT_SIZE },
5838 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5839 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5840 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5841 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5842 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5843 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5844 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5845 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5846 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5847 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5848 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5849 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005850 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005851 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5852 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5853 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5854 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5855 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5856 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005857 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005858 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005859 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005860 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005861 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005862 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005863 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005864 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005865 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005866 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005867 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005868 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5869 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005870 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5871 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005872 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005873 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005874 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005875 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005876};
5877
Johan Hedberg03811012010-12-08 00:21:06 +02005878int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5879{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005880 void *buf;
5881 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005882 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005883 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005884 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005885 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005886 int err;
5887
5888 BT_DBG("got %zu bytes", msglen);
5889
5890 if (msglen < sizeof(*hdr))
5891 return -EINVAL;
5892
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005893 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005894 if (!buf)
5895 return -ENOMEM;
5896
5897 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5898 err = -EFAULT;
5899 goto done;
5900 }
5901
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005902 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005903 opcode = __le16_to_cpu(hdr->opcode);
5904 index = __le16_to_cpu(hdr->index);
5905 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005906
5907 if (len != msglen - sizeof(*hdr)) {
5908 err = -EINVAL;
5909 goto done;
5910 }
5911
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005912 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005913 hdev = hci_dev_get(index);
5914 if (!hdev) {
5915 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005916 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005917 goto done;
5918 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005919
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005920 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005921 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005922 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005923 err = cmd_status(sk, index, opcode,
5924 MGMT_STATUS_INVALID_INDEX);
5925 goto done;
5926 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005927
5928 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005929 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005930 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5931 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005932 err = cmd_status(sk, index, opcode,
5933 MGMT_STATUS_INVALID_INDEX);
5934 goto done;
5935 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005936 }
5937
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005938 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005939 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005940 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005941 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005942 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005943 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005944 }
5945
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005946 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5947 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5948 err = cmd_status(sk, index, opcode,
5949 MGMT_STATUS_INVALID_INDEX);
5950 goto done;
5951 }
5952
5953 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5954 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005955 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005956 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005957 goto done;
5958 }
5959
Johan Hedbergbe22b542012-03-01 22:24:41 +02005960 handler = &mgmt_handlers[opcode];
5961
5962 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005963 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005964 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005965 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005966 goto done;
5967 }
5968
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005969 if (hdev)
5970 mgmt_init_hdev(sk, hdev);
5971
5972 cp = buf + sizeof(*hdr);
5973
Johan Hedbergbe22b542012-03-01 22:24:41 +02005974 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005975 if (err < 0)
5976 goto done;
5977
Johan Hedberg03811012010-12-08 00:21:06 +02005978 err = msglen;
5979
5980done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005981 if (hdev)
5982 hci_dev_put(hdev);
5983
Johan Hedberg03811012010-12-08 00:21:06 +02005984 kfree(buf);
5985 return err;
5986}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005987
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005988void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005989{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005990 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005991 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005992
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005993 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5994 return;
5995
5996 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5997 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5998 else
5999 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006000}
6001
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006002void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006003{
Johan Hedberg5f159032012-03-02 03:13:19 +02006004 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006005
Marcel Holtmann1514b892013-10-06 08:25:01 -07006006 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006007 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006008
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006009 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6010 return;
6011
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006012 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006013
Marcel Holtmannedd38962014-07-02 21:30:55 +02006014 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6015 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6016 else
6017 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006018}
6019
Andre Guedes6046dc32014-02-26 20:21:51 -03006020/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03006021static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03006022{
6023 struct hci_conn_params *p;
6024
6025 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006026 /* Needed for AUTO_OFF case where might not "really"
6027 * have been powered off.
6028 */
6029 list_del_init(&p->action);
6030
6031 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006032 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006033 case HCI_AUTO_CONN_ALWAYS:
6034 list_add(&p->action, &hdev->pend_le_conns);
6035 break;
6036 case HCI_AUTO_CONN_REPORT:
6037 list_add(&p->action, &hdev->pend_le_reports);
6038 break;
6039 default:
6040 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006041 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006042 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006043
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006044 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006045}
6046
Johan Hedberg229ab392013-03-15 17:06:53 -05006047static void powered_complete(struct hci_dev *hdev, u8 status)
6048{
6049 struct cmd_lookup match = { NULL, hdev };
6050
6051 BT_DBG("status 0x%02x", status);
6052
6053 hci_dev_lock(hdev);
6054
Johan Hedbergd7347f32014-07-04 12:37:23 +03006055 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006056
Johan Hedberg229ab392013-03-15 17:06:53 -05006057 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6058
6059 new_settings(hdev, match.sk);
6060
6061 hci_dev_unlock(hdev);
6062
6063 if (match.sk)
6064 sock_put(match.sk);
6065}
6066
Johan Hedberg70da6242013-03-15 17:06:51 -05006067static int powered_update_hci(struct hci_dev *hdev)
6068{
Johan Hedberg890ea892013-03-15 17:06:52 -05006069 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006070 u8 link_sec;
6071
Johan Hedberg890ea892013-03-15 17:06:52 -05006072 hci_req_init(&req, hdev);
6073
Johan Hedberg70da6242013-03-15 17:06:51 -05006074 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6075 !lmp_host_ssp_capable(hdev)) {
6076 u8 ssp = 1;
6077
Johan Hedberg890ea892013-03-15 17:06:52 -05006078 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006079 }
6080
Johan Hedbergc73eee92013-04-19 18:35:21 +03006081 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6082 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006083 struct hci_cp_write_le_host_supported cp;
6084
Marcel Holtmann32226e42014-07-24 20:04:16 +02006085 cp.le = 0x01;
6086 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006087
6088 /* Check first if we already have the right
6089 * host state (host features set)
6090 */
6091 if (cp.le != lmp_host_le_capable(hdev) ||
6092 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006093 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6094 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006095 }
6096
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006097 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006098 /* Make sure the controller has a good default for
6099 * advertising data. This also applies to the case
6100 * where BR/EDR was toggled during the AUTO_OFF phase.
6101 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006102 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006103 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006104 update_scan_rsp_data(&req);
6105 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006106
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006107 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6108 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006109 }
6110
Johan Hedberg70da6242013-03-15 17:06:51 -05006111 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6112 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006113 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6114 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006115
6116 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006117 write_fast_connectable(&req, false);
6118 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006119 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006120 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006121 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006122 }
6123
Johan Hedberg229ab392013-03-15 17:06:53 -05006124 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006125}
6126
Johan Hedberg744cf192011-11-08 20:40:14 +02006127int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006128{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006129 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006130 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6131 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006132 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006133
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006134 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6135 return 0;
6136
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006137 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006138 if (powered_update_hci(hdev) == 0)
6139 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006140
Johan Hedberg229ab392013-03-15 17:06:53 -05006141 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6142 &match);
6143 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006144 }
6145
Johan Hedberg229ab392013-03-15 17:06:53 -05006146 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006147 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered);
Johan Hedberg229ab392013-03-15 17:06:53 -05006148
6149 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6150 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6151 zero_cod, sizeof(zero_cod), NULL);
6152
6153new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006154 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006155
6156 if (match.sk)
6157 sock_put(match.sk);
6158
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006159 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006160}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006161
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006162void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006163{
6164 struct pending_cmd *cmd;
6165 u8 status;
6166
6167 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6168 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006169 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006170
6171 if (err == -ERFKILL)
6172 status = MGMT_STATUS_RFKILLED;
6173 else
6174 status = MGMT_STATUS_FAILED;
6175
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006176 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006177
6178 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006179}
6180
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006181void mgmt_discoverable_timeout(struct hci_dev *hdev)
6182{
6183 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006184
6185 hci_dev_lock(hdev);
6186
6187 /* When discoverable timeout triggers, then just make sure
6188 * the limited discoverable flag is cleared. Even in the case
6189 * of a timeout triggered from general discoverable, it is
6190 * safe to unconditionally clear the flag.
6191 */
6192 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006193 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006194
6195 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006196 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6197 u8 scan = SCAN_PAGE;
6198 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6199 sizeof(scan), &scan);
6200 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006201 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006202 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006203 hci_req_run(&req, NULL);
6204
6205 hdev->discov_timeout = 0;
6206
Johan Hedberg9a43e252013-10-20 19:00:07 +03006207 new_settings(hdev, NULL);
6208
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006209 hci_dev_unlock(hdev);
6210}
6211
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006212void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6213 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006214{
Johan Hedberg86742e12011-11-07 23:13:38 +02006215 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006216
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006217 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006218
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006219 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006220 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006221 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006222 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006223 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006224 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006225
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006226 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006227}
Johan Hedbergf7520542011-01-20 12:34:39 +02006228
Johan Hedbergd7b25452014-05-23 13:19:53 +03006229static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6230{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006231 switch (ltk->type) {
6232 case SMP_LTK:
6233 case SMP_LTK_SLAVE:
6234 if (ltk->authenticated)
6235 return MGMT_LTK_AUTHENTICATED;
6236 return MGMT_LTK_UNAUTHENTICATED;
6237 case SMP_LTK_P256:
6238 if (ltk->authenticated)
6239 return MGMT_LTK_P256_AUTH;
6240 return MGMT_LTK_P256_UNAUTH;
6241 case SMP_LTK_P256_DEBUG:
6242 return MGMT_LTK_P256_DEBUG;
6243 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006244
6245 return MGMT_LTK_UNAUTHENTICATED;
6246}
6247
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006248void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006249{
6250 struct mgmt_ev_new_long_term_key ev;
6251
6252 memset(&ev, 0, sizeof(ev));
6253
Marcel Holtmann5192d302014-02-19 17:11:58 -08006254 /* Devices using resolvable or non-resolvable random addresses
6255 * without providing an indentity resolving key don't require
6256 * to store long term keys. Their addresses will change the
6257 * next time around.
6258 *
6259 * Only when a remote device provides an identity address
6260 * make sure the long term key is stored. If the remote
6261 * identity is known, the long term keys are internally
6262 * mapped to the identity address. So allow static random
6263 * and public addresses here.
6264 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006265 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6266 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6267 ev.store_hint = 0x00;
6268 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006269 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006270
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006271 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006272 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006273 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006274 ev.key.enc_size = key->enc_size;
6275 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006276 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006277
Johan Hedberg2ceba532014-06-16 19:25:16 +03006278 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006279 ev.key.master = 1;
6280
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006281 memcpy(ev.key.val, key->val, sizeof(key->val));
6282
Marcel Holtmann083368f2013-10-15 14:26:29 -07006283 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006284}
6285
Johan Hedberg95fbac82014-02-19 15:18:31 +02006286void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6287{
6288 struct mgmt_ev_new_irk ev;
6289
6290 memset(&ev, 0, sizeof(ev));
6291
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006292 /* For identity resolving keys from devices that are already
6293 * using a public address or static random address, do not
6294 * ask for storing this key. The identity resolving key really
6295 * is only mandatory for devices using resovlable random
6296 * addresses.
6297 *
6298 * Storing all identity resolving keys has the downside that
6299 * they will be also loaded on next boot of they system. More
6300 * identity resolving keys, means more time during scanning is
6301 * needed to actually resolve these addresses.
6302 */
6303 if (bacmp(&irk->rpa, BDADDR_ANY))
6304 ev.store_hint = 0x01;
6305 else
6306 ev.store_hint = 0x00;
6307
Johan Hedberg95fbac82014-02-19 15:18:31 +02006308 bacpy(&ev.rpa, &irk->rpa);
6309 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6310 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6311 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6312
6313 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6314}
6315
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006316void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6317 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006318{
6319 struct mgmt_ev_new_csrk ev;
6320
6321 memset(&ev, 0, sizeof(ev));
6322
6323 /* Devices using resolvable or non-resolvable random addresses
6324 * without providing an indentity resolving key don't require
6325 * to store signature resolving keys. Their addresses will change
6326 * the next time around.
6327 *
6328 * Only when a remote device provides an identity address
6329 * make sure the signature resolving key is stored. So allow
6330 * static random and public addresses here.
6331 */
6332 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6333 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6334 ev.store_hint = 0x00;
6335 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006336 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006337
6338 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6339 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6340 ev.key.master = csrk->master;
6341 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6342
6343 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6344}
6345
Andre Guedesffb5a8272014-07-01 18:10:11 -03006346void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006347 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6348 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006349{
6350 struct mgmt_ev_new_conn_param ev;
6351
Johan Hedbergc103aea2014-07-02 17:37:34 +03006352 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6353 return;
6354
Andre Guedesffb5a8272014-07-01 18:10:11 -03006355 memset(&ev, 0, sizeof(ev));
6356 bacpy(&ev.addr.bdaddr, bdaddr);
6357 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006358 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006359 ev.min_interval = cpu_to_le16(min_interval);
6360 ev.max_interval = cpu_to_le16(max_interval);
6361 ev.latency = cpu_to_le16(latency);
6362 ev.timeout = cpu_to_le16(timeout);
6363
6364 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6365}
6366
Marcel Holtmann94933992013-10-15 10:26:39 -07006367static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6368 u8 data_len)
6369{
6370 eir[eir_len++] = sizeof(type) + data_len;
6371 eir[eir_len++] = type;
6372 memcpy(&eir[eir_len], data, data_len);
6373 eir_len += data_len;
6374
6375 return eir_len;
6376}
6377
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006378void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6379 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006380{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006381 char buf[512];
6382 struct mgmt_ev_device_connected *ev = (void *) buf;
6383 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006384
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006385 bacpy(&ev->addr.bdaddr, &conn->dst);
6386 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006387
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006388 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006389
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006390 /* We must ensure that the EIR Data fields are ordered and
6391 * unique. Keep it simple for now and avoid the problem by not
6392 * adding any BR/EDR data to the LE adv.
6393 */
6394 if (conn->le_adv_data_len > 0) {
6395 memcpy(&ev->eir[eir_len],
6396 conn->le_adv_data, conn->le_adv_data_len);
6397 eir_len = conn->le_adv_data_len;
6398 } else {
6399 if (name_len > 0)
6400 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6401 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006402
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006403 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006404 eir_len = eir_append_data(ev->eir, eir_len,
6405 EIR_CLASS_OF_DEV,
6406 conn->dev_class, 3);
6407 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006408
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006409 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006410
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006411 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6412 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006413}
6414
Johan Hedberg8962ee72011-01-20 12:40:27 +02006415static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6416{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006417 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006418
Johan Hedbergf5818c22014-12-05 13:36:02 +02006419 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006420
6421 *sk = cmd->sk;
6422 sock_hold(*sk);
6423
Johan Hedberga664b5b2011-02-19 12:06:02 -03006424 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006425}
6426
Johan Hedberg124f6e32012-02-09 13:50:12 +02006427static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006428{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006429 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006430 struct mgmt_cp_unpair_device *cp = cmd->param;
6431 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006432
6433 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006434 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6435 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006436
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006437 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6438
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006439 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006440
6441 mgmt_pending_remove(cmd);
6442}
6443
Johan Hedberg84c61d92014-08-01 11:13:30 +03006444bool mgmt_powering_down(struct hci_dev *hdev)
6445{
6446 struct pending_cmd *cmd;
6447 struct mgmt_mode *cp;
6448
6449 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6450 if (!cmd)
6451 return false;
6452
6453 cp = cmd->param;
6454 if (!cp->val)
6455 return true;
6456
6457 return false;
6458}
6459
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006460void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006461 u8 link_type, u8 addr_type, u8 reason,
6462 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006463{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006464 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006465 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006466
Johan Hedberg84c61d92014-08-01 11:13:30 +03006467 /* The connection is still in hci_conn_hash so test for 1
6468 * instead of 0 to know if this is the last one.
6469 */
6470 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6471 cancel_delayed_work(&hdev->power_off);
6472 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006473 }
6474
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006475 if (!mgmt_connected)
6476 return;
6477
Andre Guedes57eb7762013-10-30 19:01:41 -03006478 if (link_type != ACL_LINK && link_type != LE_LINK)
6479 return;
6480
Johan Hedberg744cf192011-11-08 20:40:14 +02006481 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006482
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006483 bacpy(&ev.addr.bdaddr, bdaddr);
6484 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6485 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006486
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006487 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006488
6489 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006490 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006491
Johan Hedberg124f6e32012-02-09 13:50:12 +02006492 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006493 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006494}
6495
Marcel Holtmann78929242013-10-06 23:55:47 -07006496void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6497 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006498{
Andre Guedes3655bba2013-10-30 19:01:40 -03006499 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6500 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006501 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006502
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006503 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6504 hdev);
6505
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006506 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006507 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006508 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006509
Andre Guedes3655bba2013-10-30 19:01:40 -03006510 cp = cmd->param;
6511
6512 if (bacmp(bdaddr, &cp->addr.bdaddr))
6513 return;
6514
6515 if (cp->addr.type != bdaddr_type)
6516 return;
6517
Johan Hedbergf5818c22014-12-05 13:36:02 +02006518 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006519 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006520}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006521
Marcel Holtmann445608d2013-10-06 23:55:48 -07006522void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6523 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006524{
6525 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006526
Johan Hedberg84c61d92014-08-01 11:13:30 +03006527 /* The connection is still in hci_conn_hash so test for 1
6528 * instead of 0 to know if this is the last one.
6529 */
6530 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6531 cancel_delayed_work(&hdev->power_off);
6532 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006533 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006534
Johan Hedberg4c659c32011-11-07 23:13:39 +02006535 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006536 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006537 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006538
Marcel Holtmann445608d2013-10-06 23:55:48 -07006539 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006540}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006541
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006542void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006543{
6544 struct mgmt_ev_pin_code_request ev;
6545
Johan Hedbergd8457692012-02-17 14:24:57 +02006546 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006547 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006548 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006549
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006550 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006551}
6552
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006553void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6554 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006555{
6556 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006557
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006558 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006559 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006560 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006561
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006562 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006563 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006564}
6565
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006566void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6567 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006568{
6569 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006570
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006571 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006572 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006573 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006574
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006575 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006576 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006577}
Johan Hedberga5c29682011-02-19 12:05:57 -03006578
Johan Hedberg744cf192011-11-08 20:40:14 +02006579int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006580 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006581 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006582{
6583 struct mgmt_ev_user_confirm_request ev;
6584
Johan Hedberg744cf192011-11-08 20:40:14 +02006585 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006586
Johan Hedberg272d90d2012-02-09 15:26:12 +02006587 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006588 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006589 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006590 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006591
Johan Hedberg744cf192011-11-08 20:40:14 +02006592 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006593 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006594}
6595
Johan Hedberg272d90d2012-02-09 15:26:12 +02006596int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006597 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006598{
6599 struct mgmt_ev_user_passkey_request ev;
6600
6601 BT_DBG("%s", hdev->name);
6602
Johan Hedberg272d90d2012-02-09 15:26:12 +02006603 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006604 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006605
6606 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006607 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006608}
6609
Brian Gix0df4c182011-11-16 13:53:13 -08006610static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006611 u8 link_type, u8 addr_type, u8 status,
6612 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006613{
6614 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006615
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006616 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006617 if (!cmd)
6618 return -ENOENT;
6619
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006620 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006621 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006622
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006623 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006624}
6625
Johan Hedberg744cf192011-11-08 20:40:14 +02006626int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006627 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006628{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006629 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006630 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006631}
6632
Johan Hedberg272d90d2012-02-09 15:26:12 +02006633int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006634 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006635{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006636 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006637 status,
6638 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006639}
Johan Hedberg2a611692011-02-19 12:06:00 -03006640
Brian Gix604086b2011-11-23 08:28:33 -08006641int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006642 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006643{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006644 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006645 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006646}
6647
Johan Hedberg272d90d2012-02-09 15:26:12 +02006648int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006649 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006650{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006651 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006652 status,
6653 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006654}
6655
Johan Hedberg92a25252012-09-06 18:39:26 +03006656int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6657 u8 link_type, u8 addr_type, u32 passkey,
6658 u8 entered)
6659{
6660 struct mgmt_ev_passkey_notify ev;
6661
6662 BT_DBG("%s", hdev->name);
6663
6664 bacpy(&ev.addr.bdaddr, bdaddr);
6665 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6666 ev.passkey = __cpu_to_le32(passkey);
6667 ev.entered = entered;
6668
6669 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6670}
6671
Johan Hedberge1e930f2014-09-08 17:09:49 -07006672void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006673{
6674 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006675 struct pending_cmd *cmd;
6676 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006677
Johan Hedberge1e930f2014-09-08 17:09:49 -07006678 bacpy(&ev.addr.bdaddr, &conn->dst);
6679 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6680 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006681
Johan Hedberge1e930f2014-09-08 17:09:49 -07006682 cmd = find_pairing(conn);
6683
6684 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6685 cmd ? cmd->sk : NULL);
6686
6687 if (cmd)
6688 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006689}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006690
Marcel Holtmann464996a2013-10-15 14:26:24 -07006691void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006692{
6693 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006694 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006695
6696 if (status) {
6697 u8 mgmt_err = mgmt_status(status);
6698 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006699 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006700 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006701 }
6702
Marcel Holtmann464996a2013-10-15 14:26:24 -07006703 if (test_bit(HCI_AUTH, &hdev->flags))
6704 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6705 &hdev->dev_flags);
6706 else
6707 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6708 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006709
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006710 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006711 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006712
Johan Hedberg47990ea2012-02-22 11:58:37 +02006713 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006714 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006715
6716 if (match.sk)
6717 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006718}
6719
Johan Hedberg890ea892013-03-15 17:06:52 -05006720static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006721{
Johan Hedberg890ea892013-03-15 17:06:52 -05006722 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006723 struct hci_cp_write_eir cp;
6724
Johan Hedberg976eb202012-10-24 21:12:01 +03006725 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006726 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006727
Johan Hedbergc80da272012-02-22 15:38:48 +02006728 memset(hdev->eir, 0, sizeof(hdev->eir));
6729
Johan Hedbergcacaf522012-02-21 00:52:42 +02006730 memset(&cp, 0, sizeof(cp));
6731
Johan Hedberg890ea892013-03-15 17:06:52 -05006732 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006733}
6734
Marcel Holtmann3e248562013-10-15 14:26:25 -07006735void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006736{
6737 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006738 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006739 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006740
6741 if (status) {
6742 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006743
6744 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006745 &hdev->dev_flags)) {
6746 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006747 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006748 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006749
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006750 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6751 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006752 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006753 }
6754
6755 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006756 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006757 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006758 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6759 if (!changed)
6760 changed = test_and_clear_bit(HCI_HS_ENABLED,
6761 &hdev->dev_flags);
6762 else
6763 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006764 }
6765
6766 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6767
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006768 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006769 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006770
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006771 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006772 sock_put(match.sk);
6773
Johan Hedberg890ea892013-03-15 17:06:52 -05006774 hci_req_init(&req, hdev);
6775
Johan Hedberg37699722014-06-24 14:00:27 +03006776 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6777 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6778 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6779 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006780 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006781 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006782 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006783 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006784
6785 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006786}
6787
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006788void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6789{
6790 struct cmd_lookup match = { NULL, hdev };
6791 bool changed = false;
6792
6793 if (status) {
6794 u8 mgmt_err = mgmt_status(status);
6795
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006796 if (enable) {
6797 if (test_and_clear_bit(HCI_SC_ENABLED,
6798 &hdev->dev_flags))
6799 new_settings(hdev, NULL);
6800 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6801 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006802
6803 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6804 cmd_status_rsp, &mgmt_err);
6805 return;
6806 }
6807
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006808 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006809 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006810 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006811 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006812 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6813 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006814
6815 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6816 settings_rsp, &match);
6817
6818 if (changed)
6819 new_settings(hdev, match.sk);
6820
6821 if (match.sk)
6822 sock_put(match.sk);
6823}
6824
Johan Hedberg92da6092013-03-15 17:06:55 -05006825static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006826{
6827 struct cmd_lookup *match = data;
6828
Johan Hedberg90e70452012-02-23 23:09:40 +02006829 if (match->sk == NULL) {
6830 match->sk = cmd->sk;
6831 sock_hold(match->sk);
6832 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006833}
6834
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006835void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6836 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006837{
Johan Hedberg90e70452012-02-23 23:09:40 +02006838 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006839
Johan Hedberg92da6092013-03-15 17:06:55 -05006840 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6841 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6842 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006843
6844 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006845 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6846 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006847
6848 if (match.sk)
6849 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006850}
6851
Marcel Holtmann7667da32013-10-15 14:26:27 -07006852void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006853{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006854 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006855 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006856
Johan Hedberg13928972013-03-15 17:07:00 -05006857 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006858 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006859
6860 memset(&ev, 0, sizeof(ev));
6861 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006862 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006863
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006864 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006865 if (!cmd) {
6866 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006867
Johan Hedberg13928972013-03-15 17:07:00 -05006868 /* If this is a HCI command related to powering on the
6869 * HCI dev don't send any mgmt signals.
6870 */
6871 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006872 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006873 }
6874
Marcel Holtmann7667da32013-10-15 14:26:27 -07006875 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6876 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006877}
Szymon Jancc35938b2011-03-22 13:12:21 +01006878
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006879void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006880 u8 *rand192, u8 *hash256, u8 *rand256,
6881 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006882{
6883 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006884
Johan Hedberg744cf192011-11-08 20:40:14 +02006885 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006886
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006887 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006888 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006889 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006890
6891 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006892 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6893 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006894 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006895 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006896 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006897
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006898 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006899 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006900
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006901 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006902 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006903
6904 cmd_complete(cmd->sk, hdev->id,
6905 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6906 &rp, sizeof(rp));
6907 } else {
6908 struct mgmt_rp_read_local_oob_data rp;
6909
6910 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006911 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006912
6913 cmd_complete(cmd->sk, hdev->id,
6914 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6915 &rp, sizeof(rp));
6916 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006917 }
6918
6919 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006920}
Johan Hedberge17acd42011-03-30 23:57:16 +03006921
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006922/* this is reversed hex representation of bluetooth base uuid. We need it for
6923 * service uuid parsing in eir.
6924 */
6925static const u8 reverse_base_uuid[] = {
6926 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
6927 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6928};
6929
6930static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6931{
6932 int i;
6933
6934 for (i = 0; i < uuid_count; i++) {
6935 if (!memcmp(uuid, uuids[i], 16))
6936 return true;
6937 }
6938
6939 return false;
6940}
6941
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006942static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6943{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006944 u16 parsed = 0;
6945
6946 while (parsed < eir_len) {
6947 u8 field_len = eir[0];
6948 u8 uuid[16];
6949 int i;
6950
6951 if (field_len == 0)
6952 break;
6953
6954 if (eir_len - parsed < field_len + 1)
6955 break;
6956
6957 switch (eir[1]) {
6958 case EIR_UUID16_ALL:
6959 case EIR_UUID16_SOME:
6960 for (i = 0; i + 3 <= field_len; i += 2) {
6961 memcpy(uuid, reverse_base_uuid, 16);
6962 uuid[13] = eir[i + 3];
6963 uuid[12] = eir[i + 2];
6964 if (has_uuid(uuid, uuid_count, uuids))
6965 return true;
6966 }
6967 break;
6968 case EIR_UUID32_ALL:
6969 case EIR_UUID32_SOME:
6970 for (i = 0; i + 5 <= field_len; i += 4) {
6971 memcpy(uuid, reverse_base_uuid, 16);
6972 uuid[15] = eir[i + 5];
6973 uuid[14] = eir[i + 4];
6974 uuid[13] = eir[i + 3];
6975 uuid[12] = eir[i + 2];
6976 if (has_uuid(uuid, uuid_count, uuids))
6977 return true;
6978 }
6979 break;
6980 case EIR_UUID128_ALL:
6981 case EIR_UUID128_SOME:
6982 for (i = 0; i + 17 <= field_len; i += 16) {
6983 memcpy(uuid, eir + i + 2, 16);
6984 if (has_uuid(uuid, uuid_count, uuids))
6985 return true;
6986 }
6987 break;
6988 }
6989
6990 parsed += field_len + 1;
6991 eir += field_len + 1;
6992 }
6993
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006994 return false;
6995}
6996
Marcel Holtmann901801b2013-10-06 23:55:51 -07006997void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006998 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6999 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007000{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007001 char buf[512];
7002 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007003 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007004 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007005
Johan Hedberg75ce2082014-07-02 22:42:01 +03007006 /* Don't send events for a non-kernel initiated discovery. With
7007 * LE one exception is if we have pend_le_reports > 0 in which
7008 * case we're doing passive scanning and want these events.
7009 */
7010 if (!hci_discovery_active(hdev)) {
7011 if (link_type == ACL_LINK)
7012 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007013 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007014 return;
7015 }
Andre Guedes12602d02013-04-30 15:29:40 -03007016
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007017 /* When using service discovery with a RSSI threshold, then check
7018 * if such a RSSI threshold is specified. If a RSSI threshold has
7019 * been specified, then all results with a RSSI smaller than the
7020 * RSSI threshold will be dropped.
7021 */
7022 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7023 rssi < hdev->discovery.rssi)
7024 return;
7025
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007026 /* Make sure that the buffer is big enough. The 5 extra bytes
7027 * are for the potential CoD field.
7028 */
7029 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007030 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007031
Johan Hedberg1dc06092012-01-15 21:01:23 +02007032 memset(buf, 0, sizeof(buf));
7033
Johan Hedberg841c5642014-07-07 12:45:54 +03007034 bacpy(&ev->addr.bdaddr, bdaddr);
7035 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007036 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007037 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007038
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007039 if (eir_len > 0) {
7040 /* When using service discovery and a list of UUID is
7041 * provided, results with no matching UUID should be
7042 * dropped. In case there is a match the result is
7043 * kept and checking possible scan response data
7044 * will be skipped.
7045 */
7046 if (hdev->discovery.uuid_count > 0) {
7047 match = eir_has_uuids(eir, eir_len,
7048 hdev->discovery.uuid_count,
7049 hdev->discovery.uuids);
7050 if (!match)
7051 return;
7052 }
7053
7054 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007055 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007056 } else {
7057 /* When using service discovery and a list of UUID is
7058 * provided, results with empty EIR or advertising data
7059 * should be dropped since they do not match any UUID.
7060 */
7061 if (hdev->discovery.uuid_count > 0)
7062 return;
7063 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007064
Johan Hedberg1dc06092012-01-15 21:01:23 +02007065 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7066 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007067 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007068
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007069 if (scan_rsp_len > 0) {
7070 /* When using service discovery and a list of UUID is
7071 * provided, results with no matching UUID should be
7072 * dropped if there is no previous match from the
7073 * advertising data.
7074 */
7075 if (hdev->discovery.uuid_count > 0) {
7076 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7077 hdev->discovery.uuid_count,
7078 hdev->discovery.uuids))
7079 return;
7080 }
7081
7082 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007083 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007084 } else {
7085 /* When using service discovery and a list of UUID is
7086 * provided, results with empty scan response and no
7087 * previous matched advertising data should be dropped.
7088 */
7089 if (hdev->discovery.uuid_count > 0 && !match)
7090 return;
7091 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007092
7093 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7094 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007095
Marcel Holtmann901801b2013-10-06 23:55:51 -07007096 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007097}
Johan Hedberga88a9652011-03-30 13:18:12 +03007098
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007099void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7100 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007101{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007102 struct mgmt_ev_device_found *ev;
7103 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7104 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007105
Johan Hedbergb644ba32012-01-17 21:48:47 +02007106 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007107
Johan Hedbergb644ba32012-01-17 21:48:47 +02007108 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007109
Johan Hedbergb644ba32012-01-17 21:48:47 +02007110 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007111 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007112 ev->rssi = rssi;
7113
7114 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007115 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007116
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007117 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007118
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007119 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007120}
Johan Hedberg314b2382011-04-27 10:29:57 -04007121
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007122void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007123{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007124 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007125
Andre Guedes343fb142011-11-22 17:14:19 -03007126 BT_DBG("%s discovering %u", hdev->name, discovering);
7127
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007128 memset(&ev, 0, sizeof(ev));
7129 ev.type = hdev->discovery.type;
7130 ev.discovering = discovering;
7131
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007132 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007133}
Antti Julku5e762442011-08-25 16:48:02 +03007134
Marcel Holtmann5976e602013-10-06 04:08:14 -07007135static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7136{
7137 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007138}
7139
7140void mgmt_reenable_advertising(struct hci_dev *hdev)
7141{
7142 struct hci_request req;
7143
Marcel Holtmann5976e602013-10-06 04:08:14 -07007144 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7145 return;
7146
7147 hci_req_init(&req, hdev);
7148 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007149 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007150}