blob: 376b164c5250d4de0b8f5e6820f6976941b452a6 [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 Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
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,
47 MGMT_OP_SET_PAIRABLE,
48 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,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020096};
97
98static const u16 mgmt_events[] = {
99 MGMT_EV_CONTROLLER_ERROR,
100 MGMT_EV_INDEX_ADDED,
101 MGMT_EV_INDEX_REMOVED,
102 MGMT_EV_NEW_SETTINGS,
103 MGMT_EV_CLASS_OF_DEV_CHANGED,
104 MGMT_EV_LOCAL_NAME_CHANGED,
105 MGMT_EV_NEW_LINK_KEY,
106 MGMT_EV_NEW_LONG_TERM_KEY,
107 MGMT_EV_DEVICE_CONNECTED,
108 MGMT_EV_DEVICE_DISCONNECTED,
109 MGMT_EV_CONNECT_FAILED,
110 MGMT_EV_PIN_CODE_REQUEST,
111 MGMT_EV_USER_CONFIRM_REQUEST,
112 MGMT_EV_USER_PASSKEY_REQUEST,
113 MGMT_EV_AUTH_FAILED,
114 MGMT_EV_DEVICE_FOUND,
115 MGMT_EV_DISCOVERING,
116 MGMT_EV_DEVICE_BLOCKED,
117 MGMT_EV_DEVICE_UNBLOCKED,
118 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300119 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800120 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700121 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200122 MGMT_EV_DEVICE_ADDED,
123 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300124 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200125 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200126 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200127 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200128};
129
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800130#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200131
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200132#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
133 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
134
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135struct pending_cmd {
136 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200137 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100139 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
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 Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_PAIRABLE;
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 Hedberg0f4bd942014-02-22 19:06:35 +0200580 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200582
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200583 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
584 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585 settings |= MGMT_SETTING_CONFIGURATION;
586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587 return settings;
588}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200589
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200590static u32 get_current_settings(struct hci_dev *hdev)
591{
592 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200593
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200594 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100595 settings |= MGMT_SETTING_POWERED;
596
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200597 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200598 settings |= MGMT_SETTING_CONNECTABLE;
599
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500600 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
601 settings |= MGMT_SETTING_FAST_CONNECTABLE;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_DISCOVERABLE;
605
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200606 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_PAIRABLE;
608
Johan Hedberg56f87902013-10-02 13:43:13 +0300609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_BREDR;
611
Johan Hedberg06199cf2012-02-22 16:37:11 +0200612 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200614
Johan Hedberg47990ea2012-02-22 11:58:37 +0200615 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200617
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200618 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200620
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200621 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
622 settings |= MGMT_SETTING_HS;
623
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200624 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300625 settings |= MGMT_SETTING_ADVERTISING;
626
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_SECURE_CONN;
629
Johan Hedberg0663b292014-06-24 13:15:50 +0300630 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800631 settings |= MGMT_SETTING_DEBUG_KEYS;
632
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200633 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
634 settings |= MGMT_SETTING_PRIVACY;
635
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200636 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200637}
638
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300639#define PNP_INFO_SVCLASS_ID 0x1200
640
Johan Hedberg213202e2013-01-27 00:31:33 +0200641static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
642{
643 u8 *ptr = data, *uuids_start = NULL;
644 struct bt_uuid *uuid;
645
646 if (len < 4)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 u16 uuid16;
651
652 if (uuid->size != 16)
653 continue;
654
655 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
656 if (uuid16 < 0x1100)
657 continue;
658
659 if (uuid16 == PNP_INFO_SVCLASS_ID)
660 continue;
661
662 if (!uuids_start) {
663 uuids_start = ptr;
664 uuids_start[0] = 1;
665 uuids_start[1] = EIR_UUID16_ALL;
666 ptr += 2;
667 }
668
669 /* Stop if not enough space to put next UUID */
670 if ((ptr - data) + sizeof(u16) > len) {
671 uuids_start[1] = EIR_UUID16_SOME;
672 break;
673 }
674
675 *ptr++ = (uuid16 & 0x00ff);
676 *ptr++ = (uuid16 & 0xff00) >> 8;
677 uuids_start[0] += sizeof(uuid16);
678 }
679
680 return ptr;
681}
682
Johan Hedbergcdf19632013-01-27 00:31:34 +0200683static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
684{
685 u8 *ptr = data, *uuids_start = NULL;
686 struct bt_uuid *uuid;
687
688 if (len < 6)
689 return ptr;
690
691 list_for_each_entry(uuid, &hdev->uuids, list) {
692 if (uuid->size != 32)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID32_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u32) > len) {
704 uuids_start[1] = EIR_UUID32_SOME;
705 break;
706 }
707
708 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
709 ptr += sizeof(u32);
710 uuids_start[0] += sizeof(u32);
711 }
712
713 return ptr;
714}
715
Johan Hedbergc00d5752013-01-27 00:31:35 +0200716static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 18)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 128)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID128_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + 16 > len) {
737 uuids_start[1] = EIR_UUID128_SOME;
738 break;
739 }
740
741 memcpy(ptr, uuid->uuid, 16);
742 ptr += 16;
743 uuids_start[0] += 16;
744 }
745
746 return ptr;
747}
748
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300749static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
750{
751 struct pending_cmd *cmd;
752
753 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
754 if (cmd->opcode == opcode)
755 return cmd;
756 }
757
758 return NULL;
759}
760
Johan Hedberg95868422014-06-28 17:54:07 +0300761static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
762 struct hci_dev *hdev,
763 const void *data)
764{
765 struct pending_cmd *cmd;
766
767 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
768 if (cmd->user_data != data)
769 continue;
770 if (cmd->opcode == opcode)
771 return cmd;
772 }
773
774 return NULL;
775}
776
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700777static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
778{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700779 u8 ad_len = 0;
780 size_t name_len;
781
782 name_len = strlen(hdev->dev_name);
783 if (name_len > 0) {
784 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
785
786 if (name_len > max_len) {
787 name_len = max_len;
788 ptr[1] = EIR_NAME_SHORT;
789 } else
790 ptr[1] = EIR_NAME_COMPLETE;
791
792 ptr[0] = name_len + 1;
793
794 memcpy(ptr + 2, hdev->dev_name, name_len);
795
796 ad_len += (name_len + 2);
797 ptr += (name_len + 2);
798 }
799
800 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700801}
802
803static void update_scan_rsp_data(struct hci_request *req)
804{
805 struct hci_dev *hdev = req->hdev;
806 struct hci_cp_le_set_scan_rsp_data cp;
807 u8 len;
808
Johan Hedberg7751ef12013-10-19 23:38:15 +0300809 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700810 return;
811
812 memset(&cp, 0, sizeof(cp));
813
814 len = create_scan_rsp_data(hdev, cp.data);
815
Johan Hedbergeb438b52013-10-16 15:31:07 +0300816 if (hdev->scan_rsp_data_len == len &&
817 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700818 return;
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
821 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822
823 cp.length = len;
824
825 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
826}
827
Johan Hedberg9a43e252013-10-20 19:00:07 +0300828static u8 get_adv_discov_flags(struct hci_dev *hdev)
829{
830 struct pending_cmd *cmd;
831
832 /* If there's a pending mgmt command the flags will not yet have
833 * their final values, so check for this first.
834 */
835 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
836 if (cmd) {
837 struct mgmt_mode *cp = cmd->param;
838 if (cp->val == 0x01)
839 return LE_AD_GENERAL;
840 else if (cp->val == 0x02)
841 return LE_AD_LIMITED;
842 } else {
843 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_LIMITED;
845 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_GENERAL;
847 }
848
849 return 0;
850}
851
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700852static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853{
854 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberg9a43e252013-10-20 19:00:07 +0300856 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberge8340042014-01-30 11:16:50 -0800858 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
861 if (flags) {
862 BT_DBG("adv flags 0x%02x", flags);
863
864 ptr[0] = 2;
865 ptr[1] = EIR_FLAGS;
866 ptr[2] = flags;
867
868 ad_len += 3;
869 ptr += 3;
870 }
871
872 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
873 ptr[0] = 2;
874 ptr[1] = EIR_TX_POWER;
875 ptr[2] = (u8) hdev->adv_tx_power;
876
877 ad_len += 3;
878 ptr += 3;
879 }
880
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700881 return ad_len;
882}
883
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700884static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885{
886 struct hci_dev *hdev = req->hdev;
887 struct hci_cp_le_set_adv_data cp;
888 u8 len;
889
Johan Hedberg10994ce2013-10-19 23:38:16 +0300890 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891 return;
892
893 memset(&cp, 0, sizeof(cp));
894
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700895 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896
897 if (hdev->adv_data_len == len &&
898 memcmp(cp.data, hdev->adv_data, len) == 0)
899 return;
900
901 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
902 hdev->adv_data_len = len;
903
904 cp.length = len;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
907}
908
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300909static void create_eir(struct hci_dev *hdev, u8 *data)
910{
911 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300912 size_t name_len;
913
914 name_len = strlen(hdev->dev_name);
915
916 if (name_len > 0) {
917 /* EIR Data type */
918 if (name_len > 48) {
919 name_len = 48;
920 ptr[1] = EIR_NAME_SHORT;
921 } else
922 ptr[1] = EIR_NAME_COMPLETE;
923
924 /* EIR Data length */
925 ptr[0] = name_len + 1;
926
927 memcpy(ptr + 2, hdev->dev_name, name_len);
928
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300929 ptr += (name_len + 2);
930 }
931
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100932 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700933 ptr[0] = 2;
934 ptr[1] = EIR_TX_POWER;
935 ptr[2] = (u8) hdev->inq_tx_power;
936
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700937 ptr += 3;
938 }
939
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700940 if (hdev->devid_source > 0) {
941 ptr[0] = 9;
942 ptr[1] = EIR_DEVICE_ID;
943
944 put_unaligned_le16(hdev->devid_source, ptr + 2);
945 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
946 put_unaligned_le16(hdev->devid_product, ptr + 6);
947 put_unaligned_le16(hdev->devid_version, ptr + 8);
948
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700949 ptr += 10;
950 }
951
Johan Hedberg213202e2013-01-27 00:31:33 +0200952 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200953 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200954 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300955}
956
Johan Hedberg890ea892013-03-15 17:06:52 -0500957static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300958{
Johan Hedberg890ea892013-03-15 17:06:52 -0500959 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300960 struct hci_cp_write_eir cp;
961
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200962 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500963 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200964
Johan Hedberg976eb202012-10-24 21:12:01 +0300965 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500966 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200968 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200971 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500972 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973
974 memset(&cp, 0, sizeof(cp));
975
976 create_eir(hdev, cp.data);
977
978 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
981 memcpy(hdev->eir, cp.data, sizeof(cp.data));
982
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984}
985
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200986static u8 get_service_classes(struct hci_dev *hdev)
987{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300988 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200989 u8 val = 0;
990
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300991 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200992 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200993
994 return val;
995}
996
Johan Hedberg890ea892013-03-15 17:06:52 -0500997static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200998{
Johan Hedberg890ea892013-03-15 17:06:52 -0500999 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 cod[3];
1001
1002 BT_DBG("%s", hdev->name);
1003
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001004 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001005 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001006
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001007 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1008 return;
1009
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001010 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001011 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001012
1013 cod[0] = hdev->minor_class;
1014 cod[1] = hdev->major_class;
1015 cod[2] = get_service_classes(hdev);
1016
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001017 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1018 cod[1] |= 0x20;
1019
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001020 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001024}
1025
Johan Hedberga4858cb2014-02-25 19:56:31 +02001026static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001027{
1028 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001029
1030 /* If there's a pending mgmt command the flag will not yet have
1031 * it's final value, so check for this first.
1032 */
1033 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1034 if (cmd) {
1035 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037 }
1038
Johan Hedberga4858cb2014-02-25 19:56:31 +02001039 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040}
1041
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001042static void disable_advertising(struct hci_request *req)
1043{
1044 u8 enable = 0x00;
1045
1046 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1047}
1048
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001049static void enable_advertising(struct hci_request *req)
1050{
1051 struct hci_dev *hdev = req->hdev;
1052 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001053 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001054 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001055
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001056 if (hci_conn_num(hdev, LE_LINK) > 0)
1057 return;
1058
1059 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1060 disable_advertising(req);
1061
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001062 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001063 * hci_update_random_address knows that it's safe to go ahead
1064 * and write a new random address. The flag will be set back on
1065 * as soon as the SET_ADV_ENABLE HCI command completes.
1066 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001067 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001068
Johan Hedberga4858cb2014-02-25 19:56:31 +02001069 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001070
Johan Hedberga4858cb2014-02-25 19:56:31 +02001071 /* Set require_privacy to true only when non-connectable
1072 * advertising is used. In that case it is fine to use a
1073 * non-resolvable private address.
1074 */
1075 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001076 return;
1077
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001078 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001079 cp.min_interval = cpu_to_le16(0x0800);
1080 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001081 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001082 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001083 cp.channel_map = hdev->le_adv_channel_map;
1084
1085 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1086
1087 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1088}
1089
Johan Hedberg7d785252011-12-15 00:47:39 +02001090static void service_cache_off(struct work_struct *work)
1091{
1092 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001093 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001094 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001095
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001096 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001097 return;
1098
Johan Hedberg890ea892013-03-15 17:06:52 -05001099 hci_req_init(&req, hdev);
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101 hci_dev_lock(hdev);
1102
Johan Hedberg890ea892013-03-15 17:06:52 -05001103 update_eir(&req);
1104 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001105
1106 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001107
1108 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001109}
1110
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001111static void rpa_expired(struct work_struct *work)
1112{
1113 struct hci_dev *hdev = container_of(work, struct hci_dev,
1114 rpa_expired.work);
1115 struct hci_request req;
1116
1117 BT_DBG("");
1118
1119 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1120
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001121 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122 return;
1123
1124 /* The generation of a new RPA and programming it into the
1125 * controller happens in the enable_advertising() function.
1126 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001127 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001128 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001129 hci_req_run(&req, NULL);
1130}
1131
Johan Hedberg6a919082012-02-28 06:17:26 +02001132static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001133{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001134 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001135 return;
1136
Johan Hedberg4f87da82012-03-02 19:55:56 +02001137 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001139
Johan Hedberg4f87da82012-03-02 19:55:56 +02001140 /* Non-mgmt controlled devices get this bit set
1141 * implicitly so that pairing works for them, however
1142 * for mgmt we require user-space to explicitly enable
1143 * it
1144 */
1145 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001146}
1147
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001148static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001149 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001150{
1151 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001152
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001153 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001154
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001155 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001156
Johan Hedberg03811012010-12-08 00:21:06 +02001157 memset(&rp, 0, sizeof(rp));
1158
Johan Hedberg03811012010-12-08 00:21:06 +02001159 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001160
1161 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001162 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001163
1164 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1165 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1166
1167 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001168
1169 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001170 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001171
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001172 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001174 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001175 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001176}
1177
1178static void mgmt_pending_free(struct pending_cmd *cmd)
1179{
1180 sock_put(cmd->sk);
1181 kfree(cmd->param);
1182 kfree(cmd);
1183}
1184
1185static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 struct hci_dev *hdev, void *data,
1187 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001188{
1189 struct pending_cmd *cmd;
1190
Johan Hedbergfca20012014-06-28 17:54:05 +03001191 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001192 if (!cmd)
1193 return NULL;
1194
1195 cmd->opcode = opcode;
1196 cmd->index = hdev->id;
1197
Andre Guedes12b94562012-06-07 19:05:45 -03001198 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001199 if (!cmd->param) {
1200 kfree(cmd);
1201 return NULL;
1202 }
1203
1204 if (data)
1205 memcpy(cmd->param, data, len);
1206
1207 cmd->sk = sk;
1208 sock_hold(sk);
1209
1210 list_add(&cmd->list, &hdev->mgmt_pending);
1211
1212 return cmd;
1213}
1214
1215static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001216 void (*cb)(struct pending_cmd *cmd,
1217 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001218 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001219{
Andre Guedesa3d09352013-02-01 11:21:30 -03001220 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001221
Andre Guedesa3d09352013-02-01 11:21:30 -03001222 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001223 if (opcode > 0 && cmd->opcode != opcode)
1224 continue;
1225
1226 cb(cmd, data);
1227 }
1228}
1229
Johan Hedberg03811012010-12-08 00:21:06 +02001230static void mgmt_pending_remove(struct pending_cmd *cmd)
1231{
1232 list_del(&cmd->list);
1233 mgmt_pending_free(cmd);
1234}
1235
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001236static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001237{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001238 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001239
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001240 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001241 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001242}
1243
Johan Hedberg8b064a32014-02-24 14:52:22 +02001244static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1245{
1246 BT_DBG("%s status 0x%02x", hdev->name, status);
1247
Johan Hedberga3172b72014-02-28 09:33:44 +02001248 if (hci_conn_count(hdev) == 0) {
1249 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001250 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001251 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001252}
1253
Johan Hedberg23a48092014-07-08 16:05:06 +03001254static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001255{
1256 struct hci_dev *hdev = req->hdev;
1257 struct hci_cp_remote_name_req_cancel cp;
1258 struct inquiry_entry *e;
1259
1260 switch (hdev->discovery.state) {
1261 case DISCOVERY_FINDING:
1262 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1263 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1264 } else {
1265 cancel_delayed_work(&hdev->le_scan_disable);
1266 hci_req_add_le_scan_disable(req);
1267 }
1268
Johan Hedberg23a48092014-07-08 16:05:06 +03001269 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001270
1271 case DISCOVERY_RESOLVING:
1272 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1273 NAME_PENDING);
1274 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001275 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001276
1277 bacpy(&cp.bdaddr, &e->data.bdaddr);
1278 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1279 &cp);
1280
Johan Hedberg23a48092014-07-08 16:05:06 +03001281 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001282
1283 default:
1284 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001287 return true;
1288 }
1289
Johan Hedberg21a60d32014-06-10 14:05:58 +03001290 break;
1291 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001292
1293 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001294}
1295
Johan Hedberg8b064a32014-02-24 14:52:22 +02001296static int clean_up_hci_state(struct hci_dev *hdev)
1297{
1298 struct hci_request req;
1299 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001300 bool discov_stopped;
1301 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001302
1303 hci_req_init(&req, hdev);
1304
1305 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1306 test_bit(HCI_PSCAN, &hdev->flags)) {
1307 u8 scan = 0x00;
1308 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1309 }
1310
Johan Hedberg73e082f2014-07-08 15:07:51 +03001311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312 disable_advertising(&req);
1313
Johan Hedberg23a48092014-07-08 16:05:06 +03001314 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001315
1316 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1317 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001318 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001319
Johan Hedbergc9910d02014-02-27 14:35:12 +02001320 switch (conn->state) {
1321 case BT_CONNECTED:
1322 case BT_CONFIG:
1323 dc.handle = cpu_to_le16(conn->handle);
1324 dc.reason = 0x15; /* Terminated due to Power Off */
1325 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1326 break;
1327 case BT_CONNECT:
1328 if (conn->type == LE_LINK)
1329 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1330 0, NULL);
1331 else if (conn->type == ACL_LINK)
1332 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1333 6, &conn->dst);
1334 break;
1335 case BT_CONNECT2:
1336 bacpy(&rej.bdaddr, &conn->dst);
1337 rej.reason = 0x15; /* Terminated due to Power Off */
1338 if (conn->type == ACL_LINK)
1339 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1340 sizeof(rej), &rej);
1341 else if (conn->type == SCO_LINK)
1342 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1343 sizeof(rej), &rej);
1344 break;
1345 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001346 }
1347
Johan Hedberg23a48092014-07-08 16:05:06 +03001348 err = hci_req_run(&req, clean_up_hci_complete);
1349 if (!err && discov_stopped)
1350 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1351
1352 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001353}
1354
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001355static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001356 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001357{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001358 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001359 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001360 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001362 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001363
Johan Hedberga7e80f22013-01-09 16:05:19 +02001364 if (cp->val != 0x00 && cp->val != 0x01)
1365 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1366 MGMT_STATUS_INVALID_PARAMS);
1367
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001368 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001369
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001370 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1371 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1372 MGMT_STATUS_BUSY);
1373 goto failed;
1374 }
1375
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001376 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1377 cancel_delayed_work(&hdev->power_off);
1378
1379 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001380 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1381 data, len);
1382 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001383 goto failed;
1384 }
1385 }
1386
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001387 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001388 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001389 goto failed;
1390 }
1391
Johan Hedberg03811012010-12-08 00:21:06 +02001392 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1393 if (!cmd) {
1394 err = -ENOMEM;
1395 goto failed;
1396 }
1397
Johan Hedberg8b064a32014-02-24 14:52:22 +02001398 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001399 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001400 err = 0;
1401 } else {
1402 /* Disconnect connections, stop scans, etc */
1403 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001404 if (!err)
1405 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1406 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 /* ENODATA means there were no HCI commands queued */
1409 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001410 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001411 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1412 err = 0;
1413 }
1414 }
Johan Hedberg03811012010-12-08 00:21:06 +02001415
1416failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001417 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001418 return err;
1419}
1420
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001421static int new_settings(struct hci_dev *hdev, struct sock *skip)
1422{
1423 __le32 ev;
1424
1425 ev = cpu_to_le32(get_current_settings(hdev));
1426
1427 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1428}
1429
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001430struct cmd_lookup {
1431 struct sock *sk;
1432 struct hci_dev *hdev;
1433 u8 mgmt_status;
1434};
1435
1436static void settings_rsp(struct pending_cmd *cmd, void *data)
1437{
1438 struct cmd_lookup *match = data;
1439
1440 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1441
1442 list_del(&cmd->list);
1443
1444 if (match->sk == NULL) {
1445 match->sk = cmd->sk;
1446 sock_hold(match->sk);
1447 }
1448
1449 mgmt_pending_free(cmd);
1450}
1451
1452static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1453{
1454 u8 *status = data;
1455
1456 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1457 mgmt_pending_remove(cmd);
1458}
1459
Johan Hedberge6fe7982013-10-02 15:45:22 +03001460static u8 mgmt_bredr_support(struct hci_dev *hdev)
1461{
1462 if (!lmp_bredr_capable(hdev))
1463 return MGMT_STATUS_NOT_SUPPORTED;
1464 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1465 return MGMT_STATUS_REJECTED;
1466 else
1467 return MGMT_STATUS_SUCCESS;
1468}
1469
1470static u8 mgmt_le_support(struct hci_dev *hdev)
1471{
1472 if (!lmp_le_capable(hdev))
1473 return MGMT_STATUS_NOT_SUPPORTED;
1474 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1475 return MGMT_STATUS_REJECTED;
1476 else
1477 return MGMT_STATUS_SUCCESS;
1478}
1479
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001480static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1481{
1482 struct pending_cmd *cmd;
1483 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001484 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001485 bool changed;
1486
1487 BT_DBG("status 0x%02x", status);
1488
1489 hci_dev_lock(hdev);
1490
1491 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1492 if (!cmd)
1493 goto unlock;
1494
1495 if (status) {
1496 u8 mgmt_err = mgmt_status(status);
1497 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001498 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001499 goto remove_cmd;
1500 }
1501
1502 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001503 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1505 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001506
1507 if (hdev->discov_timeout > 0) {
1508 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1509 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1510 to);
1511 }
1512 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001513 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1514 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001515 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001516
1517 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1518
1519 if (changed)
1520 new_settings(hdev, cmd->sk);
1521
Marcel Holtmann970ba522013-10-15 06:33:57 -07001522 /* When the discoverable mode gets changed, make sure
1523 * that class of device has the limited discoverable
1524 * bit correctly set.
1525 */
1526 hci_req_init(&req, hdev);
1527 update_class(&req);
1528 hci_req_run(&req, NULL);
1529
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001530remove_cmd:
1531 mgmt_pending_remove(cmd);
1532
1533unlock:
1534 hci_dev_unlock(hdev);
1535}
1536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001537static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001538 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001539{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001540 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001541 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001542 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001543 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001544 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001545 int err;
1546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001547 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001548
Johan Hedberg9a43e252013-10-20 19:00:07 +03001549 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1550 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001551 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001552 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001553
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001554 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001555 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1556 MGMT_STATUS_INVALID_PARAMS);
1557
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001558 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001559
1560 /* Disabling discoverable requires that no timeout is set,
1561 * and enabling limited discoverable requires a timeout.
1562 */
1563 if ((cp->val == 0x00 && timeout > 0) ||
1564 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001565 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001566 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001567
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001568 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001569
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001570 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001571 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001572 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001573 goto failed;
1574 }
1575
1576 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001577 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001578 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001579 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001580 goto failed;
1581 }
1582
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001583 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001584 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001585 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 goto failed;
1587 }
1588
1589 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001590 bool changed = false;
1591
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001592 /* Setting limited discoverable when powered off is
1593 * not a valid operation since it requires a timeout
1594 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1595 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001596 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1597 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1598 changed = true;
1599 }
1600
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001601 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001602 if (err < 0)
1603 goto failed;
1604
1605 if (changed)
1606 err = new_settings(hdev, sk);
1607
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001608 goto failed;
1609 }
1610
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001611 /* If the current mode is the same, then just update the timeout
1612 * value with the new value. And if only the timeout gets updated,
1613 * then no need for any HCI transactions.
1614 */
1615 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1616 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1617 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001618 cancel_delayed_work(&hdev->discov_off);
1619 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001620
Marcel Holtmann36261542013-10-15 08:28:51 -07001621 if (cp->val && hdev->discov_timeout > 0) {
1622 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001623 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001624 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001625 }
1626
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001627 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001628 goto failed;
1629 }
1630
1631 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1632 if (!cmd) {
1633 err = -ENOMEM;
1634 goto failed;
1635 }
1636
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001637 /* Cancel any potential discoverable timeout that might be
1638 * still active and store new timeout value. The arming of
1639 * the timeout happens in the complete handler.
1640 */
1641 cancel_delayed_work(&hdev->discov_off);
1642 hdev->discov_timeout = timeout;
1643
Johan Hedbergb456f872013-10-19 23:38:22 +03001644 /* Limited discoverable mode */
1645 if (cp->val == 0x02)
1646 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1647 else
1648 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1649
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001650 hci_req_init(&req, hdev);
1651
Johan Hedberg9a43e252013-10-20 19:00:07 +03001652 /* The procedure for LE-only controllers is much simpler - just
1653 * update the advertising data.
1654 */
1655 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1656 goto update_ad;
1657
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001658 scan = SCAN_PAGE;
1659
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001660 if (cp->val) {
1661 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001662
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001663 if (cp->val == 0x02) {
1664 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001665 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001666 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1667 hci_cp.iac_lap[1] = 0x8b;
1668 hci_cp.iac_lap[2] = 0x9e;
1669 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1670 hci_cp.iac_lap[4] = 0x8b;
1671 hci_cp.iac_lap[5] = 0x9e;
1672 } else {
1673 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001674 hci_cp.num_iac = 1;
1675 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1676 hci_cp.iac_lap[1] = 0x8b;
1677 hci_cp.iac_lap[2] = 0x9e;
1678 }
1679
1680 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1681 (hci_cp.num_iac * 3) + 1, &hci_cp);
1682
1683 scan |= SCAN_INQUIRY;
1684 } else {
1685 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1686 }
1687
1688 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001689
Johan Hedberg9a43e252013-10-20 19:00:07 +03001690update_ad:
1691 update_adv_data(&req);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001694 if (err < 0)
1695 mgmt_pending_remove(cmd);
1696
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001697failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001698 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001699 return err;
1700}
1701
Johan Hedberg406d7802013-03-15 17:07:09 -05001702static void write_fast_connectable(struct hci_request *req, bool enable)
1703{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001704 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001705 struct hci_cp_write_page_scan_activity acp;
1706 u8 type;
1707
Johan Hedberg547003b2013-10-21 16:51:53 +03001708 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1709 return;
1710
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001711 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1712 return;
1713
Johan Hedberg406d7802013-03-15 17:07:09 -05001714 if (enable) {
1715 type = PAGE_SCAN_TYPE_INTERLACED;
1716
1717 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001718 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001719 } else {
1720 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1721
1722 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001723 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001724 }
1725
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001726 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001727
Johan Hedbergbd98b992013-03-15 17:07:13 -05001728 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1729 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1730 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1731 sizeof(acp), &acp);
1732
1733 if (hdev->page_scan_type != type)
1734 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001735}
1736
Johan Hedberg2b76f452013-03-15 17:07:04 -05001737static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1738{
1739 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001740 struct mgmt_mode *cp;
1741 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001742
1743 BT_DBG("status 0x%02x", status);
1744
1745 hci_dev_lock(hdev);
1746
1747 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1748 if (!cmd)
1749 goto unlock;
1750
Johan Hedberg37438c12013-10-14 16:20:05 +03001751 if (status) {
1752 u8 mgmt_err = mgmt_status(status);
1753 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1754 goto remove_cmd;
1755 }
1756
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001757 cp = cmd->param;
1758 if (cp->val)
1759 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1760 else
1761 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1762
Johan Hedberg2b76f452013-03-15 17:07:04 -05001763 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1764
Johan Hedberg2b7be332014-07-07 14:40:22 +03001765 if (changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001766 new_settings(hdev, cmd->sk);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001767 hci_update_background_scan(hdev);
1768 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001769
Johan Hedberg37438c12013-10-14 16:20:05 +03001770remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001771 mgmt_pending_remove(cmd);
1772
1773unlock:
1774 hci_dev_unlock(hdev);
1775}
1776
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001777static int set_connectable_update_settings(struct hci_dev *hdev,
1778 struct sock *sk, u8 val)
1779{
1780 bool changed = false;
1781 int err;
1782
1783 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1784 changed = true;
1785
1786 if (val) {
1787 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1788 } else {
1789 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1790 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1791 }
1792
1793 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1794 if (err < 0)
1795 return err;
1796
1797 if (changed)
1798 return new_settings(hdev, sk);
1799
1800 return 0;
1801}
1802
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001803static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001804 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001805{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001806 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001807 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001808 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001809 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001810 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001811
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001812 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001813
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001814 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1815 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001816 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001817 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001818
Johan Hedberga7e80f22013-01-09 16:05:19 +02001819 if (cp->val != 0x00 && cp->val != 0x01)
1820 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1821 MGMT_STATUS_INVALID_PARAMS);
1822
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001823 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001824
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001825 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001826 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001827 goto failed;
1828 }
1829
1830 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001831 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001832 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001833 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001834 goto failed;
1835 }
1836
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001837 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1838 if (!cmd) {
1839 err = -ENOMEM;
1840 goto failed;
1841 }
1842
Johan Hedberg2b76f452013-03-15 17:07:04 -05001843 hci_req_init(&req, hdev);
1844
Johan Hedberg9a43e252013-10-20 19:00:07 +03001845 /* If BR/EDR is not enabled and we disable advertising as a
1846 * by-product of disabling connectable, we need to update the
1847 * advertising flags.
1848 */
1849 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1850 if (!cp->val) {
1851 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1852 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1853 }
1854 update_adv_data(&req);
1855 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001856 if (cp->val) {
1857 scan = SCAN_PAGE;
1858 } else {
1859 scan = 0;
1860
1861 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001862 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001863 cancel_delayed_work(&hdev->discov_off);
1864 }
1865
1866 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1867 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001868
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001869 /* If we're going from non-connectable to connectable or
1870 * vice-versa when fast connectable is enabled ensure that fast
1871 * connectable gets disabled. write_fast_connectable won't do
1872 * anything if the page scan parameters are already what they
1873 * should be.
1874 */
1875 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001876 write_fast_connectable(&req, false);
1877
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001878 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001879 !test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001880 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001881
Johan Hedberg2b76f452013-03-15 17:07:04 -05001882 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001883 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001884 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001885 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001886 err = set_connectable_update_settings(hdev, sk,
1887 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001888 goto failed;
1889 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001890
1891failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001892 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001893 return err;
1894}
1895
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001896static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001897 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001898{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001899 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001900 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001901 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001902
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001903 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001904
Johan Hedberga7e80f22013-01-09 16:05:19 +02001905 if (cp->val != 0x00 && cp->val != 0x01)
1906 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1907 MGMT_STATUS_INVALID_PARAMS);
1908
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001909 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001910
1911 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001912 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001913 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001914 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001915
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001916 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001917 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001918 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001919
Marcel Holtmann55594352013-10-06 16:11:57 -07001920 if (changed)
1921 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001922
Marcel Holtmann55594352013-10-06 16:11:57 -07001923unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001924 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001925 return err;
1926}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001927
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001928static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1929 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001930{
1931 struct mgmt_mode *cp = data;
1932 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001933 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001934 int err;
1935
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001936 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001937
Johan Hedberge6fe7982013-10-02 15:45:22 +03001938 status = mgmt_bredr_support(hdev);
1939 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001940 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001941 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001942
Johan Hedberga7e80f22013-01-09 16:05:19 +02001943 if (cp->val != 0x00 && cp->val != 0x01)
1944 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1945 MGMT_STATUS_INVALID_PARAMS);
1946
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001947 hci_dev_lock(hdev);
1948
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001949 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001950 bool changed = false;
1951
1952 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001953 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001954 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1955 changed = true;
1956 }
1957
1958 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1959 if (err < 0)
1960 goto failed;
1961
1962 if (changed)
1963 err = new_settings(hdev, sk);
1964
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001965 goto failed;
1966 }
1967
1968 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001969 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001970 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001971 goto failed;
1972 }
1973
1974 val = !!cp->val;
1975
1976 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1977 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1978 goto failed;
1979 }
1980
1981 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1982 if (!cmd) {
1983 err = -ENOMEM;
1984 goto failed;
1985 }
1986
1987 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1988 if (err < 0) {
1989 mgmt_pending_remove(cmd);
1990 goto failed;
1991 }
1992
1993failed:
1994 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001995 return err;
1996}
1997
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001998static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001999{
2000 struct mgmt_mode *cp = data;
2001 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002002 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002003 int err;
2004
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002005 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002006
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002007 status = mgmt_bredr_support(hdev);
2008 if (status)
2009 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2010
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002011 if (!lmp_ssp_capable(hdev))
2012 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2013 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002014
Johan Hedberga7e80f22013-01-09 16:05:19 +02002015 if (cp->val != 0x00 && cp->val != 0x01)
2016 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2017 MGMT_STATUS_INVALID_PARAMS);
2018
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002019 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002020
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002021 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002022 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002023
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002024 if (cp->val) {
2025 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2026 &hdev->dev_flags);
2027 } else {
2028 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2029 &hdev->dev_flags);
2030 if (!changed)
2031 changed = test_and_clear_bit(HCI_HS_ENABLED,
2032 &hdev->dev_flags);
2033 else
2034 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002035 }
2036
2037 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2038 if (err < 0)
2039 goto failed;
2040
2041 if (changed)
2042 err = new_settings(hdev, sk);
2043
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002044 goto failed;
2045 }
2046
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002047 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2048 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002049 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2050 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002051 goto failed;
2052 }
2053
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002054 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002055 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2056 goto failed;
2057 }
2058
2059 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2060 if (!cmd) {
2061 err = -ENOMEM;
2062 goto failed;
2063 }
2064
Johan Hedberg37699722014-06-24 14:00:27 +03002065 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2066 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2067 sizeof(cp->val), &cp->val);
2068
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002069 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002070 if (err < 0) {
2071 mgmt_pending_remove(cmd);
2072 goto failed;
2073 }
2074
2075failed:
2076 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002077 return err;
2078}
2079
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002080static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002081{
2082 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002083 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002084 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002085 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002086
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002087 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002088
Johan Hedberge6fe7982013-10-02 15:45:22 +03002089 status = mgmt_bredr_support(hdev);
2090 if (status)
2091 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002092
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002093 if (!lmp_ssp_capable(hdev))
2094 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2095 MGMT_STATUS_NOT_SUPPORTED);
2096
2097 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2098 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2099 MGMT_STATUS_REJECTED);
2100
Johan Hedberga7e80f22013-01-09 16:05:19 +02002101 if (cp->val != 0x00 && cp->val != 0x01)
2102 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2103 MGMT_STATUS_INVALID_PARAMS);
2104
Marcel Holtmannee392692013-10-01 22:59:23 -07002105 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002106
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002107 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002108 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002109 } else {
2110 if (hdev_is_powered(hdev)) {
2111 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2112 MGMT_STATUS_REJECTED);
2113 goto unlock;
2114 }
2115
Marcel Holtmannee392692013-10-01 22:59:23 -07002116 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002117 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002118
2119 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2120 if (err < 0)
2121 goto unlock;
2122
2123 if (changed)
2124 err = new_settings(hdev, sk);
2125
2126unlock:
2127 hci_dev_unlock(hdev);
2128 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002129}
2130
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002131static void le_enable_complete(struct hci_dev *hdev, u8 status)
2132{
2133 struct cmd_lookup match = { NULL, hdev };
2134
2135 if (status) {
2136 u8 mgmt_err = mgmt_status(status);
2137
2138 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2139 &mgmt_err);
2140 return;
2141 }
2142
2143 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2144
2145 new_settings(hdev, match.sk);
2146
2147 if (match.sk)
2148 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002149
2150 /* Make sure the controller has a good default for
2151 * advertising data. Restrict the update to when LE
2152 * has actually been enabled. During power on, the
2153 * update in powered_update_hci will take care of it.
2154 */
2155 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2156 struct hci_request req;
2157
2158 hci_dev_lock(hdev);
2159
2160 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002161 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002162 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002163 hci_req_run(&req, NULL);
2164
Johan Hedberga70f4b52014-07-07 15:19:50 +03002165 hci_update_background_scan(hdev);
2166
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002167 hci_dev_unlock(hdev);
2168 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002169}
2170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002171static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002172{
2173 struct mgmt_mode *cp = data;
2174 struct hci_cp_write_le_host_supported hci_cp;
2175 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002176 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002177 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002178 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002180 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002181
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002182 if (!lmp_le_capable(hdev))
2183 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2184 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002185
Johan Hedberga7e80f22013-01-09 16:05:19 +02002186 if (cp->val != 0x00 && cp->val != 0x01)
2187 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2188 MGMT_STATUS_INVALID_PARAMS);
2189
Johan Hedbergc73eee92013-04-19 18:35:21 +03002190 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002191 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002192 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2193 MGMT_STATUS_REJECTED);
2194
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002195 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002196
2197 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002198 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002199
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002200 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002201 bool changed = false;
2202
2203 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2204 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2205 changed = true;
2206 }
2207
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002208 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2209 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002210 changed = true;
2211 }
2212
Johan Hedberg06199cf2012-02-22 16:37:11 +02002213 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2214 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002215 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002216
2217 if (changed)
2218 err = new_settings(hdev, sk);
2219
Johan Hedberg1de028c2012-02-29 19:55:35 -08002220 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002221 }
2222
Johan Hedberg4375f102013-09-25 13:26:10 +03002223 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2224 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002225 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002226 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002227 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002228 }
2229
2230 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2231 if (!cmd) {
2232 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002233 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002234 }
2235
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002236 hci_req_init(&req, hdev);
2237
Johan Hedberg06199cf2012-02-22 16:37:11 +02002238 memset(&hci_cp, 0, sizeof(hci_cp));
2239
2240 if (val) {
2241 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002242 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002243 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002244 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002245 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246 }
2247
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002248 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2249 &hci_cp);
2250
2251 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302252 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002253 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002254
Johan Hedberg1de028c2012-02-29 19:55:35 -08002255unlock:
2256 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002257 return err;
2258}
2259
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002260/* This is a helper function to test for pending mgmt commands that can
2261 * cause CoD or EIR HCI commands. We can only allow one such pending
2262 * mgmt command at a time since otherwise we cannot easily track what
2263 * the current values are, will be, and based on that calculate if a new
2264 * HCI command needs to be sent and if yes with what value.
2265 */
2266static bool pending_eir_or_class(struct hci_dev *hdev)
2267{
2268 struct pending_cmd *cmd;
2269
2270 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2271 switch (cmd->opcode) {
2272 case MGMT_OP_ADD_UUID:
2273 case MGMT_OP_REMOVE_UUID:
2274 case MGMT_OP_SET_DEV_CLASS:
2275 case MGMT_OP_SET_POWERED:
2276 return true;
2277 }
2278 }
2279
2280 return false;
2281}
2282
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002283static const u8 bluetooth_base_uuid[] = {
2284 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2285 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2286};
2287
2288static u8 get_uuid_size(const u8 *uuid)
2289{
2290 u32 val;
2291
2292 if (memcmp(uuid, bluetooth_base_uuid, 12))
2293 return 128;
2294
2295 val = get_unaligned_le32(&uuid[12]);
2296 if (val > 0xffff)
2297 return 32;
2298
2299 return 16;
2300}
2301
Johan Hedberg92da6092013-03-15 17:06:55 -05002302static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2303{
2304 struct pending_cmd *cmd;
2305
2306 hci_dev_lock(hdev);
2307
2308 cmd = mgmt_pending_find(mgmt_op, hdev);
2309 if (!cmd)
2310 goto unlock;
2311
2312 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2313 hdev->dev_class, 3);
2314
2315 mgmt_pending_remove(cmd);
2316
2317unlock:
2318 hci_dev_unlock(hdev);
2319}
2320
2321static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2322{
2323 BT_DBG("status 0x%02x", status);
2324
2325 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2326}
2327
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002328static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002329{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002330 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002331 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002332 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002333 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002334 int err;
2335
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002336 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002337
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002338 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002339
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002340 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002341 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002342 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002343 goto failed;
2344 }
2345
Andre Guedes92c4c202012-06-07 19:05:44 -03002346 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002347 if (!uuid) {
2348 err = -ENOMEM;
2349 goto failed;
2350 }
2351
2352 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002353 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002354 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002355
Johan Hedbergde66aa62013-01-27 00:31:27 +02002356 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002357
Johan Hedberg890ea892013-03-15 17:06:52 -05002358 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002359
Johan Hedberg890ea892013-03-15 17:06:52 -05002360 update_class(&req);
2361 update_eir(&req);
2362
Johan Hedberg92da6092013-03-15 17:06:55 -05002363 err = hci_req_run(&req, add_uuid_complete);
2364 if (err < 0) {
2365 if (err != -ENODATA)
2366 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002367
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002368 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002369 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002370 goto failed;
2371 }
2372
2373 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002374 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002375 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002376 goto failed;
2377 }
2378
2379 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002380
2381failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002382 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002383 return err;
2384}
2385
Johan Hedberg24b78d02012-02-23 23:24:30 +02002386static bool enable_service_cache(struct hci_dev *hdev)
2387{
2388 if (!hdev_is_powered(hdev))
2389 return false;
2390
2391 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002392 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2393 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002394 return true;
2395 }
2396
2397 return false;
2398}
2399
Johan Hedberg92da6092013-03-15 17:06:55 -05002400static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2401{
2402 BT_DBG("status 0x%02x", status);
2403
2404 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2405}
2406
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002407static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002408 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002409{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002410 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002411 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002412 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002413 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 -05002414 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002415 int err, found;
2416
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002417 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002418
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002419 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002420
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002421 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002422 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002423 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002424 goto unlock;
2425 }
2426
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002427 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002428 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002429
Johan Hedberg24b78d02012-02-23 23:24:30 +02002430 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002431 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002432 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002433 goto unlock;
2434 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002435
Johan Hedberg9246a862012-02-23 21:33:16 +02002436 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002437 }
2438
2439 found = 0;
2440
Johan Hedberg056341c2013-01-27 00:31:30 +02002441 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002442 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2443 continue;
2444
2445 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002446 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447 found++;
2448 }
2449
2450 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002451 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002452 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002453 goto unlock;
2454 }
2455
Johan Hedberg9246a862012-02-23 21:33:16 +02002456update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002457 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002458
Johan Hedberg890ea892013-03-15 17:06:52 -05002459 update_class(&req);
2460 update_eir(&req);
2461
Johan Hedberg92da6092013-03-15 17:06:55 -05002462 err = hci_req_run(&req, remove_uuid_complete);
2463 if (err < 0) {
2464 if (err != -ENODATA)
2465 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002466
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002467 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002468 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002469 goto unlock;
2470 }
2471
2472 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002473 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002474 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002475 goto unlock;
2476 }
2477
2478 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002479
2480unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002481 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 return err;
2483}
2484
Johan Hedberg92da6092013-03-15 17:06:55 -05002485static void set_class_complete(struct hci_dev *hdev, u8 status)
2486{
2487 BT_DBG("status 0x%02x", status);
2488
2489 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2490}
2491
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002492static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002493 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002494{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002495 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002496 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002497 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002498 int err;
2499
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002500 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002501
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002502 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002503 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2504 MGMT_STATUS_NOT_SUPPORTED);
2505
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002506 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002507
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002508 if (pending_eir_or_class(hdev)) {
2509 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2510 MGMT_STATUS_BUSY);
2511 goto unlock;
2512 }
2513
2514 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2515 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2516 MGMT_STATUS_INVALID_PARAMS);
2517 goto unlock;
2518 }
2519
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002520 hdev->major_class = cp->major;
2521 hdev->minor_class = cp->minor;
2522
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002523 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002524 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002525 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002526 goto unlock;
2527 }
2528
Johan Hedberg890ea892013-03-15 17:06:52 -05002529 hci_req_init(&req, hdev);
2530
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002531 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002532 hci_dev_unlock(hdev);
2533 cancel_delayed_work_sync(&hdev->service_cache);
2534 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002535 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002536 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002537
Johan Hedberg890ea892013-03-15 17:06:52 -05002538 update_class(&req);
2539
Johan Hedberg92da6092013-03-15 17:06:55 -05002540 err = hci_req_run(&req, set_class_complete);
2541 if (err < 0) {
2542 if (err != -ENODATA)
2543 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002544
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002545 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002546 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002547 goto unlock;
2548 }
2549
2550 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002551 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002552 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002553 goto unlock;
2554 }
2555
2556 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002557
Johan Hedbergb5235a62012-02-21 14:32:24 +02002558unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002559 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002560 return err;
2561}
2562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002563static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002564 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002565{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002566 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002567 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2568 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002569 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002570 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002571 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002572
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002573 BT_DBG("request for %s", hdev->name);
2574
2575 if (!lmp_bredr_capable(hdev))
2576 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2577 MGMT_STATUS_NOT_SUPPORTED);
2578
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002579 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002580 if (key_count > max_key_count) {
2581 BT_ERR("load_link_keys: too big key_count value %u",
2582 key_count);
2583 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2584 MGMT_STATUS_INVALID_PARAMS);
2585 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002586
Johan Hedberg86742e12011-11-07 23:13:38 +02002587 expected_len = sizeof(*cp) + key_count *
2588 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002589 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002590 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002591 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002593 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002594 }
2595
Johan Hedberg4ae14302013-01-20 14:27:13 +02002596 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2597 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2598 MGMT_STATUS_INVALID_PARAMS);
2599
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002600 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002601 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002602
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002603 for (i = 0; i < key_count; i++) {
2604 struct mgmt_link_key_info *key = &cp->keys[i];
2605
Marcel Holtmann8e991132014-01-10 02:07:25 -08002606 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002607 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2608 MGMT_STATUS_INVALID_PARAMS);
2609 }
2610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002611 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002612
2613 hci_link_keys_clear(hdev);
2614
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002615 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002616 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2617 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002618 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002619 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2620 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002621
2622 if (changed)
2623 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002624
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002625 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002626 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002627
Johan Hedberg58e92932014-06-24 14:00:26 +03002628 /* Always ignore debug keys and require a new pairing if
2629 * the user wants to use them.
2630 */
2631 if (key->type == HCI_LK_DEBUG_COMBINATION)
2632 continue;
2633
Johan Hedberg7652ff62014-06-24 13:15:49 +03002634 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2635 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002636 }
2637
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002638 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002639
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002640 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002641
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002642 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002643}
2644
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002645static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002646 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002647{
2648 struct mgmt_ev_device_unpaired ev;
2649
2650 bacpy(&ev.addr.bdaddr, bdaddr);
2651 ev.addr.type = addr_type;
2652
2653 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002654 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002655}
2656
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002657static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002658 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002659{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002660 struct mgmt_cp_unpair_device *cp = data;
2661 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002662 struct hci_cp_disconnect dc;
2663 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002664 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002665 int err;
2666
Johan Hedberga8a1d192011-11-10 15:54:38 +02002667 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002668 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2669 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002670
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002671 if (!bdaddr_type_is_valid(cp->addr.type))
2672 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2673 MGMT_STATUS_INVALID_PARAMS,
2674 &rp, sizeof(rp));
2675
Johan Hedberg118da702013-01-20 14:27:20 +02002676 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2677 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2678 MGMT_STATUS_INVALID_PARAMS,
2679 &rp, sizeof(rp));
2680
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002681 hci_dev_lock(hdev);
2682
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002683 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002684 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002685 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002686 goto unlock;
2687 }
2688
Johan Hedberge0b2b272014-02-18 17:14:31 +02002689 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002690 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002691 } else {
2692 u8 addr_type;
2693
2694 if (cp->addr.type == BDADDR_LE_PUBLIC)
2695 addr_type = ADDR_LE_DEV_PUBLIC;
2696 else
2697 addr_type = ADDR_LE_DEV_RANDOM;
2698
Johan Hedberga7ec7332014-02-18 17:14:35 +02002699 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2700
Andre Guedesa9b0a042014-02-26 20:21:52 -03002701 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2702
Johan Hedberge0b2b272014-02-18 17:14:31 +02002703 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2704 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002705
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002706 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002707 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002708 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002709 goto unlock;
2710 }
2711
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002712 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002713 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002714 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002715 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002716 else
2717 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002718 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002719 } else {
2720 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002721 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002722
Johan Hedberga8a1d192011-11-10 15:54:38 +02002723 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002726 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002727 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002728 }
2729
Johan Hedberg124f6e32012-02-09 13:50:12 +02002730 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002731 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002732 if (!cmd) {
2733 err = -ENOMEM;
2734 goto unlock;
2735 }
2736
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002737 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002738 dc.reason = 0x13; /* Remote User Terminated Connection */
2739 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2740 if (err < 0)
2741 mgmt_pending_remove(cmd);
2742
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002743unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002744 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002745 return err;
2746}
2747
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002748static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002749 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002750{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002751 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002752 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002753 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002754 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002755 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002756 int err;
2757
2758 BT_DBG("");
2759
Johan Hedberg06a63b12013-01-20 14:27:21 +02002760 memset(&rp, 0, sizeof(rp));
2761 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2762 rp.addr.type = cp->addr.type;
2763
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002764 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002765 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2766 MGMT_STATUS_INVALID_PARAMS,
2767 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002768
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002769 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002770
2771 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002772 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2773 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002774 goto failed;
2775 }
2776
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002777 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002778 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2779 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002780 goto failed;
2781 }
2782
Andre Guedes591f47f2012-04-24 21:02:49 -03002783 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002784 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2785 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002786 else
2787 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002788
Vishal Agarwalf9607272012-06-13 05:32:43 +05302789 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002790 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2791 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002792 goto failed;
2793 }
2794
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002795 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002796 if (!cmd) {
2797 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002798 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002799 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002800
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002801 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002802 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002803
2804 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2805 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002806 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002807
2808failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002809 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002810 return err;
2811}
2812
Andre Guedes57c14772012-04-24 21:02:50 -03002813static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002814{
2815 switch (link_type) {
2816 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002817 switch (addr_type) {
2818 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002819 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002820
Johan Hedberg48264f02011-11-09 13:58:58 +02002821 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002822 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002823 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002824 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002825
Johan Hedberg4c659c32011-11-07 23:13:39 +02002826 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002827 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002828 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002829 }
2830}
2831
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002832static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2833 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002834{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002835 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002836 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002837 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002838 int err;
2839 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002840
2841 BT_DBG("");
2842
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002843 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002844
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002845 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002846 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002847 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002848 goto unlock;
2849 }
2850
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002851 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002852 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2853 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002854 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002855 }
2856
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002857 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002858 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002859 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002860 err = -ENOMEM;
2861 goto unlock;
2862 }
2863
Johan Hedberg2784eb42011-01-21 13:56:35 +02002864 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002865 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002866 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2867 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002868 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002869 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002870 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002871 continue;
2872 i++;
2873 }
2874
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002875 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002876
Johan Hedberg4c659c32011-11-07 23:13:39 +02002877 /* Recalculate length in case of filtered SCO connections, etc */
2878 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002879
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002880 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002881 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002882
Johan Hedberga38528f2011-01-22 06:46:43 +02002883 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002884
2885unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002886 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002887 return err;
2888}
2889
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002890static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002891 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002892{
2893 struct pending_cmd *cmd;
2894 int err;
2895
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002896 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002897 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002898 if (!cmd)
2899 return -ENOMEM;
2900
Johan Hedbergd8457692012-02-17 14:24:57 +02002901 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002902 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002903 if (err < 0)
2904 mgmt_pending_remove(cmd);
2905
2906 return err;
2907}
2908
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002909static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002910 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002911{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002912 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002913 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002914 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002915 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002916 int err;
2917
2918 BT_DBG("");
2919
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002920 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002921
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002922 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002923 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002924 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002925 goto failed;
2926 }
2927
Johan Hedbergd8457692012-02-17 14:24:57 +02002928 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002929 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002930 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002931 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002932 goto failed;
2933 }
2934
2935 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002936 struct mgmt_cp_pin_code_neg_reply ncp;
2937
2938 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002939
2940 BT_ERR("PIN code is not 16 bytes long");
2941
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002942 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002943 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002944 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002945 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002946
2947 goto failed;
2948 }
2949
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002950 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002951 if (!cmd) {
2952 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002953 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002954 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002955
Johan Hedbergd8457692012-02-17 14:24:57 +02002956 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002957 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002958 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002959
2960 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2961 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002962 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002963
2964failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002965 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002966 return err;
2967}
2968
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002969static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2970 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002971{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002972 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002973
2974 BT_DBG("");
2975
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002976 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2977 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2978 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2979
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002980 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002981
2982 hdev->io_capability = cp->io_capability;
2983
2984 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002985 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002986
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002987 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002988
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002989 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2990 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002991}
2992
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002993static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002994{
2995 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002996 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002997
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002998 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002999 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3000 continue;
3001
Johan Hedberge9a416b2011-02-19 12:05:56 -03003002 if (cmd->user_data != conn)
3003 continue;
3004
3005 return cmd;
3006 }
3007
3008 return NULL;
3009}
3010
3011static void pairing_complete(struct pending_cmd *cmd, u8 status)
3012{
3013 struct mgmt_rp_pair_device rp;
3014 struct hci_conn *conn = cmd->user_data;
3015
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003016 bacpy(&rp.addr.bdaddr, &conn->dst);
3017 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003018
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003019 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003020 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003021
3022 /* So we don't get further callbacks for this connection */
3023 conn->connect_cfm_cb = NULL;
3024 conn->security_cfm_cb = NULL;
3025 conn->disconn_cfm_cb = NULL;
3026
David Herrmann76a68ba2013-04-06 20:28:37 +02003027 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003028
Johan Hedberga664b5b2011-02-19 12:06:02 -03003029 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003030}
3031
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003032void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3033{
3034 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3035 struct pending_cmd *cmd;
3036
3037 cmd = find_pairing(conn);
3038 if (cmd)
3039 pairing_complete(cmd, status);
3040}
3041
Johan Hedberge9a416b2011-02-19 12:05:56 -03003042static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3043{
3044 struct pending_cmd *cmd;
3045
3046 BT_DBG("status %u", status);
3047
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003048 cmd = find_pairing(conn);
3049 if (!cmd)
3050 BT_DBG("Unable to find a pending command");
3051 else
Johan Hedberge2113262012-02-18 15:20:03 +02003052 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003053}
3054
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003055static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303056{
3057 struct pending_cmd *cmd;
3058
3059 BT_DBG("status %u", status);
3060
3061 if (!status)
3062 return;
3063
3064 cmd = find_pairing(conn);
3065 if (!cmd)
3066 BT_DBG("Unable to find a pending command");
3067 else
3068 pairing_complete(cmd, mgmt_status(status));
3069}
3070
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003071static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003072 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003073{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003074 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003075 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003076 struct pending_cmd *cmd;
3077 u8 sec_level, auth_type;
3078 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003079 int err;
3080
3081 BT_DBG("");
3082
Szymon Jancf950a30e2013-01-18 12:48:07 +01003083 memset(&rp, 0, sizeof(rp));
3084 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3085 rp.addr.type = cp->addr.type;
3086
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003087 if (!bdaddr_type_is_valid(cp->addr.type))
3088 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3089 MGMT_STATUS_INVALID_PARAMS,
3090 &rp, sizeof(rp));
3091
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003092 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3093 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3094 MGMT_STATUS_INVALID_PARAMS,
3095 &rp, sizeof(rp));
3096
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003097 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003098
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003099 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003100 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3101 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003102 goto unlock;
3103 }
3104
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003105 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003106 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003107
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003108 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003109 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3110 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003111 } else {
3112 u8 addr_type;
3113
3114 /* Convert from L2CAP channel address type to HCI address type
3115 */
3116 if (cp->addr.type == BDADDR_LE_PUBLIC)
3117 addr_type = ADDR_LE_DEV_PUBLIC;
3118 else
3119 addr_type = ADDR_LE_DEV_RANDOM;
3120
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003121 /* When pairing a new device, it is expected to remember
3122 * this device for future connections. Adding the connection
3123 * parameter information ahead of time allows tracking
3124 * of the slave preferred values and will speed up any
3125 * further connection establishment.
3126 *
3127 * If connection parameters already exist, then they
3128 * will be kept and this function does nothing.
3129 */
3130 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3131
Johan Hedbergcdd62752014-07-07 15:02:28 +03003132 /* Request a connection with master = true role */
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003133 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedbergcdd62752014-07-07 15:02:28 +03003134 sec_level, HCI_LE_CONN_TIMEOUT, true);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003135 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003136
Ville Tervo30e76272011-02-22 16:10:53 -03003137 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003138 int status;
3139
3140 if (PTR_ERR(conn) == -EBUSY)
3141 status = MGMT_STATUS_BUSY;
3142 else
3143 status = MGMT_STATUS_CONNECT_FAILED;
3144
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003145 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003146 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003147 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148 goto unlock;
3149 }
3150
3151 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003152 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003153 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003154 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003155 goto unlock;
3156 }
3157
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003158 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003159 if (!cmd) {
3160 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003161 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003162 goto unlock;
3163 }
3164
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003165 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003166 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003167 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003168 conn->security_cfm_cb = pairing_complete_cb;
3169 conn->disconn_cfm_cb = pairing_complete_cb;
3170 } else {
3171 conn->connect_cfm_cb = le_pairing_complete_cb;
3172 conn->security_cfm_cb = le_pairing_complete_cb;
3173 conn->disconn_cfm_cb = le_pairing_complete_cb;
3174 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003175
Johan Hedberge9a416b2011-02-19 12:05:56 -03003176 conn->io_capability = cp->io_cap;
3177 cmd->user_data = conn;
3178
3179 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003180 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003181 pairing_complete(cmd, 0);
3182
3183 err = 0;
3184
3185unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003186 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003187 return err;
3188}
3189
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003190static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3191 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003192{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003193 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003194 struct pending_cmd *cmd;
3195 struct hci_conn *conn;
3196 int err;
3197
3198 BT_DBG("");
3199
Johan Hedberg28424702012-02-02 04:02:29 +02003200 hci_dev_lock(hdev);
3201
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003202 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003203 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003204 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003205 goto unlock;
3206 }
3207
Johan Hedberg28424702012-02-02 04:02:29 +02003208 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3209 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003210 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003211 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003212 goto unlock;
3213 }
3214
3215 conn = cmd->user_data;
3216
3217 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003218 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003219 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003220 goto unlock;
3221 }
3222
3223 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3224
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003225 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003226 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003227unlock:
3228 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003229 return err;
3230}
3231
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003232static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003233 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003234 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003235{
Johan Hedberga5c29682011-02-19 12:05:57 -03003236 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003237 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003238 int err;
3239
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003240 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003241
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003242 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003243 err = cmd_complete(sk, hdev->id, mgmt_op,
3244 MGMT_STATUS_NOT_POWERED, addr,
3245 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003246 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003247 }
3248
Johan Hedberg1707c602013-03-15 17:07:15 -05003249 if (addr->type == BDADDR_BREDR)
3250 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003251 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003252 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003253
Johan Hedberg272d90d2012-02-09 15:26:12 +02003254 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003255 err = cmd_complete(sk, hdev->id, mgmt_op,
3256 MGMT_STATUS_NOT_CONNECTED, addr,
3257 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003258 goto done;
3259 }
3260
Johan Hedberg1707c602013-03-15 17:07:15 -05003261 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003262 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003263 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003264 err = cmd_complete(sk, hdev->id, mgmt_op,
3265 MGMT_STATUS_SUCCESS, addr,
3266 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003267 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003268 err = cmd_complete(sk, hdev->id, mgmt_op,
3269 MGMT_STATUS_FAILED, addr,
3270 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003271
Brian Gix47c15e22011-11-16 13:53:14 -08003272 goto done;
3273 }
3274
Johan Hedberg1707c602013-03-15 17:07:15 -05003275 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003276 if (!cmd) {
3277 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003278 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003279 }
3280
Brian Gix0df4c182011-11-16 13:53:13 -08003281 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003282 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3283 struct hci_cp_user_passkey_reply cp;
3284
Johan Hedberg1707c602013-03-15 17:07:15 -05003285 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003286 cp.passkey = passkey;
3287 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3288 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003289 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3290 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003291
Johan Hedberga664b5b2011-02-19 12:06:02 -03003292 if (err < 0)
3293 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003294
Brian Gix0df4c182011-11-16 13:53:13 -08003295done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003296 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003297 return err;
3298}
3299
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303300static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3301 void *data, u16 len)
3302{
3303 struct mgmt_cp_pin_code_neg_reply *cp = data;
3304
3305 BT_DBG("");
3306
Johan Hedberg1707c602013-03-15 17:07:15 -05003307 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303308 MGMT_OP_PIN_CODE_NEG_REPLY,
3309 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3310}
3311
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003312static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3313 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003314{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003315 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003316
3317 BT_DBG("");
3318
3319 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003320 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003321 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003322
Johan Hedberg1707c602013-03-15 17:07:15 -05003323 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003324 MGMT_OP_USER_CONFIRM_REPLY,
3325 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003326}
3327
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003328static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003329 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003330{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003331 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003332
3333 BT_DBG("");
3334
Johan Hedberg1707c602013-03-15 17:07:15 -05003335 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003336 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3337 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003338}
3339
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003340static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3341 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003342{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003343 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003344
3345 BT_DBG("");
3346
Johan Hedberg1707c602013-03-15 17:07:15 -05003347 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003348 MGMT_OP_USER_PASSKEY_REPLY,
3349 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003350}
3351
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003352static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003353 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003354{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003355 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003356
3357 BT_DBG("");
3358
Johan Hedberg1707c602013-03-15 17:07:15 -05003359 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003360 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3361 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003362}
3363
Johan Hedberg13928972013-03-15 17:07:00 -05003364static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003365{
Johan Hedberg13928972013-03-15 17:07:00 -05003366 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003367 struct hci_cp_write_local_name cp;
3368
Johan Hedberg13928972013-03-15 17:07:00 -05003369 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003370
Johan Hedberg890ea892013-03-15 17:06:52 -05003371 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003372}
3373
Johan Hedberg13928972013-03-15 17:07:00 -05003374static void set_name_complete(struct hci_dev *hdev, u8 status)
3375{
3376 struct mgmt_cp_set_local_name *cp;
3377 struct pending_cmd *cmd;
3378
3379 BT_DBG("status 0x%02x", status);
3380
3381 hci_dev_lock(hdev);
3382
3383 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3384 if (!cmd)
3385 goto unlock;
3386
3387 cp = cmd->param;
3388
3389 if (status)
3390 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3391 mgmt_status(status));
3392 else
3393 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3394 cp, sizeof(*cp));
3395
3396 mgmt_pending_remove(cmd);
3397
3398unlock:
3399 hci_dev_unlock(hdev);
3400}
3401
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003402static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003403 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003404{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003405 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003406 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003407 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003408 int err;
3409
3410 BT_DBG("");
3411
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003412 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003413
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003414 /* If the old values are the same as the new ones just return a
3415 * direct command complete event.
3416 */
3417 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3418 !memcmp(hdev->short_name, cp->short_name,
3419 sizeof(hdev->short_name))) {
3420 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3421 data, len);
3422 goto failed;
3423 }
3424
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003425 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003426
Johan Hedbergb5235a62012-02-21 14:32:24 +02003427 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003428 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003429
3430 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003431 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003432 if (err < 0)
3433 goto failed;
3434
3435 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003436 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003437
Johan Hedbergb5235a62012-02-21 14:32:24 +02003438 goto failed;
3439 }
3440
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003441 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003442 if (!cmd) {
3443 err = -ENOMEM;
3444 goto failed;
3445 }
3446
Johan Hedberg13928972013-03-15 17:07:00 -05003447 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3448
Johan Hedberg890ea892013-03-15 17:06:52 -05003449 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003450
3451 if (lmp_bredr_capable(hdev)) {
3452 update_name(&req);
3453 update_eir(&req);
3454 }
3455
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003456 /* The name is stored in the scan response data and so
3457 * no need to udpate the advertising data here.
3458 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003459 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003460 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003461
Johan Hedberg13928972013-03-15 17:07:00 -05003462 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003463 if (err < 0)
3464 mgmt_pending_remove(cmd);
3465
3466failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003467 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003468 return err;
3469}
3470
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003471static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003472 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003473{
Szymon Jancc35938b2011-03-22 13:12:21 +01003474 struct pending_cmd *cmd;
3475 int err;
3476
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003477 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003478
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003479 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003480
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003481 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003483 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003484 goto unlock;
3485 }
3486
Andre Guedes9a1a1992012-07-24 15:03:48 -03003487 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003488 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003489 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003490 goto unlock;
3491 }
3492
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003493 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003494 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003495 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003496 goto unlock;
3497 }
3498
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003499 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003500 if (!cmd) {
3501 err = -ENOMEM;
3502 goto unlock;
3503 }
3504
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003505 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3506 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3507 0, NULL);
3508 else
3509 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3510
Szymon Jancc35938b2011-03-22 13:12:21 +01003511 if (err < 0)
3512 mgmt_pending_remove(cmd);
3513
3514unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003515 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003516 return err;
3517}
3518
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003519static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003520 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003521{
Szymon Janc2763eda2011-03-22 13:12:22 +01003522 int err;
3523
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003524 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003525
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003526 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003527
Marcel Holtmannec109112014-01-10 02:07:30 -08003528 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3529 struct mgmt_cp_add_remote_oob_data *cp = data;
3530 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003531
Marcel Holtmannec109112014-01-10 02:07:30 -08003532 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3533 cp->hash, cp->randomizer);
3534 if (err < 0)
3535 status = MGMT_STATUS_FAILED;
3536 else
3537 status = MGMT_STATUS_SUCCESS;
3538
3539 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3540 status, &cp->addr, sizeof(cp->addr));
3541 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3542 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3543 u8 status;
3544
3545 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3546 cp->hash192,
3547 cp->randomizer192,
3548 cp->hash256,
3549 cp->randomizer256);
3550 if (err < 0)
3551 status = MGMT_STATUS_FAILED;
3552 else
3553 status = MGMT_STATUS_SUCCESS;
3554
3555 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3556 status, &cp->addr, sizeof(cp->addr));
3557 } else {
3558 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3559 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3560 MGMT_STATUS_INVALID_PARAMS);
3561 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003562
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003563 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003564 return err;
3565}
3566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003567static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003568 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003569{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003570 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003571 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003572 int err;
3573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003574 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003575
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003576 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003577
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003578 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003579 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003580 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003581 else
Szymon Janca6785be2012-12-13 15:11:21 +01003582 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003584 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003585 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003586
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003587 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003588 return err;
3589}
3590
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003591static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3592{
3593 struct pending_cmd *cmd;
3594 u8 type;
3595 int err;
3596
3597 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3598
3599 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3600 if (!cmd)
3601 return -ENOENT;
3602
3603 type = hdev->discovery.type;
3604
3605 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3606 &type, sizeof(type));
3607 mgmt_pending_remove(cmd);
3608
3609 return err;
3610}
3611
Andre Guedes7c307722013-04-30 15:29:28 -03003612static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3613{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003614 unsigned long timeout = 0;
3615
Andre Guedes7c307722013-04-30 15:29:28 -03003616 BT_DBG("status %d", status);
3617
3618 if (status) {
3619 hci_dev_lock(hdev);
3620 mgmt_start_discovery_failed(hdev, status);
3621 hci_dev_unlock(hdev);
3622 return;
3623 }
3624
3625 hci_dev_lock(hdev);
3626 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3627 hci_dev_unlock(hdev);
3628
3629 switch (hdev->discovery.type) {
3630 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003631 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003632 break;
3633
3634 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003635 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003636 break;
3637
3638 case DISCOV_TYPE_BREDR:
3639 break;
3640
3641 default:
3642 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3643 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003644
3645 if (!timeout)
3646 return;
3647
3648 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003649}
3650
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003651static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003652 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003653{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003654 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003655 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003656 struct hci_cp_le_set_scan_param param_cp;
3657 struct hci_cp_le_set_scan_enable enable_cp;
3658 struct hci_cp_inquiry inq_cp;
3659 struct hci_request req;
3660 /* General inquiry access code (GIAC) */
3661 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003662 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003663 int err;
3664
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003665 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003666
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003667 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003668
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003669 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003670 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003671 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003672 goto failed;
3673 }
3674
Andre Guedes642be6c2012-03-21 00:03:37 -03003675 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3676 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3677 MGMT_STATUS_BUSY);
3678 goto failed;
3679 }
3680
Johan Hedbergff9ef572012-01-04 14:23:45 +02003681 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003682 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003683 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003684 goto failed;
3685 }
3686
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003687 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003688 if (!cmd) {
3689 err = -ENOMEM;
3690 goto failed;
3691 }
3692
Andre Guedes4aab14e2012-02-17 20:39:36 -03003693 hdev->discovery.type = cp->type;
3694
Andre Guedes7c307722013-04-30 15:29:28 -03003695 hci_req_init(&req, hdev);
3696
Andre Guedes4aab14e2012-02-17 20:39:36 -03003697 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003698 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003699 status = mgmt_bredr_support(hdev);
3700 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003701 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003702 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003703 mgmt_pending_remove(cmd);
3704 goto failed;
3705 }
3706
Andre Guedes7c307722013-04-30 15:29:28 -03003707 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3708 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3709 MGMT_STATUS_BUSY);
3710 mgmt_pending_remove(cmd);
3711 goto failed;
3712 }
3713
3714 hci_inquiry_cache_flush(hdev);
3715
3716 memset(&inq_cp, 0, sizeof(inq_cp));
3717 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003718 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003719 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003720 break;
3721
3722 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003723 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003724 status = mgmt_le_support(hdev);
3725 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003726 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003727 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003728 mgmt_pending_remove(cmd);
3729 goto failed;
3730 }
3731
Andre Guedes7c307722013-04-30 15:29:28 -03003732 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003733 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003734 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3735 MGMT_STATUS_NOT_SUPPORTED);
3736 mgmt_pending_remove(cmd);
3737 goto failed;
3738 }
3739
Johan Hedberge8bb6b92014-07-08 15:07:53 +03003740 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3741 /* Don't let discovery abort an outgoing
3742 * connection attempt that's using directed
3743 * advertising.
3744 */
3745 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3746 BT_CONNECT)) {
3747 err = cmd_status(sk, hdev->id,
3748 MGMT_OP_START_DISCOVERY,
3749 MGMT_STATUS_REJECTED);
3750 mgmt_pending_remove(cmd);
3751 goto failed;
3752 }
3753
3754 disable_advertising(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003755 }
3756
Andre Guedesc54c3862014-02-26 20:21:50 -03003757 /* If controller is scanning, it means the background scanning
3758 * is running. Thus, we should temporarily stop it in order to
3759 * set the discovery scanning parameters.
3760 */
3761 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3762 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003763
3764 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003765
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003766 /* All active scans will be done with either a resolvable
3767 * private address (when privacy feature has been enabled)
3768 * or unresolvable private address.
3769 */
3770 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003771 if (err < 0) {
3772 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3773 MGMT_STATUS_FAILED);
3774 mgmt_pending_remove(cmd);
3775 goto failed;
3776 }
3777
Andre Guedes7c307722013-04-30 15:29:28 -03003778 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003779 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3780 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003781 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003782 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3783 &param_cp);
3784
3785 memset(&enable_cp, 0, sizeof(enable_cp));
3786 enable_cp.enable = LE_SCAN_ENABLE;
3787 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3788 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3789 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003790 break;
3791
Andre Guedesf39799f2012-02-17 20:39:35 -03003792 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003793 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3794 MGMT_STATUS_INVALID_PARAMS);
3795 mgmt_pending_remove(cmd);
3796 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003797 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003798
Andre Guedes7c307722013-04-30 15:29:28 -03003799 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003800 if (err < 0)
3801 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003802 else
3803 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003804
3805failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003806 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003807 return err;
3808}
3809
Andre Guedes1183fdc2013-04-30 15:29:35 -03003810static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3811{
3812 struct pending_cmd *cmd;
3813 int err;
3814
3815 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3816 if (!cmd)
3817 return -ENOENT;
3818
3819 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3820 &hdev->discovery.type, sizeof(hdev->discovery.type));
3821 mgmt_pending_remove(cmd);
3822
3823 return err;
3824}
3825
Andre Guedes0e05bba2013-04-30 15:29:33 -03003826static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3827{
3828 BT_DBG("status %d", status);
3829
3830 hci_dev_lock(hdev);
3831
3832 if (status) {
3833 mgmt_stop_discovery_failed(hdev, status);
3834 goto unlock;
3835 }
3836
3837 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3838
3839unlock:
3840 hci_dev_unlock(hdev);
3841}
3842
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003843static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003844 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003845{
Johan Hedbergd9306502012-02-20 23:25:18 +02003846 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003847 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003848 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003849 int err;
3850
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003851 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003852
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003853 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003854
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003855 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003856 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003857 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3858 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003859 goto unlock;
3860 }
3861
3862 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003863 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003864 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3865 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003866 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003867 }
3868
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003869 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003870 if (!cmd) {
3871 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003872 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003873 }
3874
Andre Guedes0e05bba2013-04-30 15:29:33 -03003875 hci_req_init(&req, hdev);
3876
Johan Hedberg21a60d32014-06-10 14:05:58 +03003877 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003878
Johan Hedberg21a60d32014-06-10 14:05:58 +03003879 err = hci_req_run(&req, stop_discovery_complete);
3880 if (!err) {
3881 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003882 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003883 }
3884
Johan Hedberg21a60d32014-06-10 14:05:58 +03003885 mgmt_pending_remove(cmd);
3886
3887 /* If no HCI commands were sent we're done */
3888 if (err == -ENODATA) {
3889 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3890 &mgmt_cp->type, sizeof(mgmt_cp->type));
3891 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3892 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003893
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003894unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003895 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003896 return err;
3897}
3898
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003899static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003900 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003901{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003902 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003903 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003904 int err;
3905
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003906 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003907
Johan Hedberg561aafb2012-01-04 13:31:59 +02003908 hci_dev_lock(hdev);
3909
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003910 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003911 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3912 MGMT_STATUS_FAILED, &cp->addr,
3913 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003914 goto failed;
3915 }
3916
Johan Hedberga198e7b2012-02-17 14:27:06 +02003917 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003918 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003919 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3920 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3921 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003922 goto failed;
3923 }
3924
3925 if (cp->name_known) {
3926 e->name_state = NAME_KNOWN;
3927 list_del(&e->list);
3928 } else {
3929 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003930 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003931 }
3932
Johan Hedberge3846622013-01-09 15:29:33 +02003933 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3934 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003935
3936failed:
3937 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003938 return err;
3939}
3940
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003941static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003942 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003943{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003944 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003945 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003946 int err;
3947
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003948 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003949
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003950 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003951 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3952 MGMT_STATUS_INVALID_PARAMS,
3953 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003954
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003955 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003956
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003957 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003958 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003959 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003960 goto done;
3961 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003962
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003963 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3964 sk);
3965 status = MGMT_STATUS_SUCCESS;
3966
3967done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003968 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003969 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003970
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003971 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003972
3973 return err;
3974}
3975
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003976static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003977 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003978{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003979 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003980 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003981 int err;
3982
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003983 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003984
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003985 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003986 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3987 MGMT_STATUS_INVALID_PARAMS,
3988 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003989
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003990 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003991
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003992 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003993 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003994 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003995 goto done;
3996 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003997
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003998 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3999 sk);
4000 status = MGMT_STATUS_SUCCESS;
4001
4002done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004003 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004004 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004005
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004006 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004007
4008 return err;
4009}
4010
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004011static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4012 u16 len)
4013{
4014 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004015 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004016 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004017 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004018
4019 BT_DBG("%s", hdev->name);
4020
Szymon Jancc72d4b82012-03-16 16:02:57 +01004021 source = __le16_to_cpu(cp->source);
4022
4023 if (source > 0x0002)
4024 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4025 MGMT_STATUS_INVALID_PARAMS);
4026
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004027 hci_dev_lock(hdev);
4028
Szymon Jancc72d4b82012-03-16 16:02:57 +01004029 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004030 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4031 hdev->devid_product = __le16_to_cpu(cp->product);
4032 hdev->devid_version = __le16_to_cpu(cp->version);
4033
4034 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4035
Johan Hedberg890ea892013-03-15 17:06:52 -05004036 hci_req_init(&req, hdev);
4037 update_eir(&req);
4038 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004039
4040 hci_dev_unlock(hdev);
4041
4042 return err;
4043}
4044
Johan Hedberg4375f102013-09-25 13:26:10 +03004045static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4046{
4047 struct cmd_lookup match = { NULL, hdev };
4048
4049 if (status) {
4050 u8 mgmt_err = mgmt_status(status);
4051
4052 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4053 cmd_status_rsp, &mgmt_err);
4054 return;
4055 }
4056
Johan Hedbergc93bd152014-07-08 15:07:48 +03004057 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4058 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4059 else
4060 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4061
Johan Hedberg4375f102013-09-25 13:26:10 +03004062 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4063 &match);
4064
4065 new_settings(hdev, match.sk);
4066
4067 if (match.sk)
4068 sock_put(match.sk);
4069}
4070
Marcel Holtmann21b51872013-10-10 09:47:53 -07004071static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4072 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004073{
4074 struct mgmt_mode *cp = data;
4075 struct pending_cmd *cmd;
4076 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004077 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004078 int err;
4079
4080 BT_DBG("request for %s", hdev->name);
4081
Johan Hedberge6fe7982013-10-02 15:45:22 +03004082 status = mgmt_le_support(hdev);
4083 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004084 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004085 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004086
4087 if (cp->val != 0x00 && cp->val != 0x01)
4088 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4089 MGMT_STATUS_INVALID_PARAMS);
4090
4091 hci_dev_lock(hdev);
4092
4093 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004094 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004095
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004096 /* The following conditions are ones which mean that we should
4097 * not do any HCI communication but directly send a mgmt
4098 * response to user space (after toggling the flag if
4099 * necessary).
4100 */
4101 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004102 hci_conn_num(hdev, LE_LINK) > 0 ||
4103 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4104 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004105 bool changed = false;
4106
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004107 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4108 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004109 changed = true;
4110 }
4111
4112 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4113 if (err < 0)
4114 goto unlock;
4115
4116 if (changed)
4117 err = new_settings(hdev, sk);
4118
4119 goto unlock;
4120 }
4121
4122 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4123 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4124 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4125 MGMT_STATUS_BUSY);
4126 goto unlock;
4127 }
4128
4129 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4130 if (!cmd) {
4131 err = -ENOMEM;
4132 goto unlock;
4133 }
4134
4135 hci_req_init(&req, hdev);
4136
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004137 if (val)
4138 enable_advertising(&req);
4139 else
4140 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004141
4142 err = hci_req_run(&req, set_advertising_complete);
4143 if (err < 0)
4144 mgmt_pending_remove(cmd);
4145
4146unlock:
4147 hci_dev_unlock(hdev);
4148 return err;
4149}
4150
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004151static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4152 void *data, u16 len)
4153{
4154 struct mgmt_cp_set_static_address *cp = data;
4155 int err;
4156
4157 BT_DBG("%s", hdev->name);
4158
Marcel Holtmann62af4442013-10-02 22:10:32 -07004159 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004160 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004161 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004162
4163 if (hdev_is_powered(hdev))
4164 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4165 MGMT_STATUS_REJECTED);
4166
4167 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4168 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4169 return cmd_status(sk, hdev->id,
4170 MGMT_OP_SET_STATIC_ADDRESS,
4171 MGMT_STATUS_INVALID_PARAMS);
4172
4173 /* Two most significant bits shall be set */
4174 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4175 return cmd_status(sk, hdev->id,
4176 MGMT_OP_SET_STATIC_ADDRESS,
4177 MGMT_STATUS_INVALID_PARAMS);
4178 }
4179
4180 hci_dev_lock(hdev);
4181
4182 bacpy(&hdev->static_addr, &cp->bdaddr);
4183
4184 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4185
4186 hci_dev_unlock(hdev);
4187
4188 return err;
4189}
4190
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004191static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4192 void *data, u16 len)
4193{
4194 struct mgmt_cp_set_scan_params *cp = data;
4195 __u16 interval, window;
4196 int err;
4197
4198 BT_DBG("%s", hdev->name);
4199
4200 if (!lmp_le_capable(hdev))
4201 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4202 MGMT_STATUS_NOT_SUPPORTED);
4203
4204 interval = __le16_to_cpu(cp->interval);
4205
4206 if (interval < 0x0004 || interval > 0x4000)
4207 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4208 MGMT_STATUS_INVALID_PARAMS);
4209
4210 window = __le16_to_cpu(cp->window);
4211
4212 if (window < 0x0004 || window > 0x4000)
4213 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4214 MGMT_STATUS_INVALID_PARAMS);
4215
Marcel Holtmann899e1072013-10-14 09:55:32 -07004216 if (window > interval)
4217 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4218 MGMT_STATUS_INVALID_PARAMS);
4219
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004220 hci_dev_lock(hdev);
4221
4222 hdev->le_scan_interval = interval;
4223 hdev->le_scan_window = window;
4224
4225 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4226
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004227 /* If background scan is running, restart it so new parameters are
4228 * loaded.
4229 */
4230 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4231 hdev->discovery.state == DISCOVERY_STOPPED) {
4232 struct hci_request req;
4233
4234 hci_req_init(&req, hdev);
4235
4236 hci_req_add_le_scan_disable(&req);
4237 hci_req_add_le_passive_scan(&req);
4238
4239 hci_req_run(&req, NULL);
4240 }
4241
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004242 hci_dev_unlock(hdev);
4243
4244 return err;
4245}
4246
Johan Hedberg33e38b32013-03-15 17:07:05 -05004247static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4248{
4249 struct pending_cmd *cmd;
4250
4251 BT_DBG("status 0x%02x", status);
4252
4253 hci_dev_lock(hdev);
4254
4255 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4256 if (!cmd)
4257 goto unlock;
4258
4259 if (status) {
4260 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4261 mgmt_status(status));
4262 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004263 struct mgmt_mode *cp = cmd->param;
4264
4265 if (cp->val)
4266 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4267 else
4268 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4269
Johan Hedberg33e38b32013-03-15 17:07:05 -05004270 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4271 new_settings(hdev, cmd->sk);
4272 }
4273
4274 mgmt_pending_remove(cmd);
4275
4276unlock:
4277 hci_dev_unlock(hdev);
4278}
4279
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004280static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004281 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004282{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004283 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004284 struct pending_cmd *cmd;
4285 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004286 int err;
4287
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004288 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004289
Johan Hedberg56f87902013-10-02 13:43:13 +03004290 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4291 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004292 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4293 MGMT_STATUS_NOT_SUPPORTED);
4294
Johan Hedberga7e80f22013-01-09 16:05:19 +02004295 if (cp->val != 0x00 && cp->val != 0x01)
4296 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4297 MGMT_STATUS_INVALID_PARAMS);
4298
Johan Hedberg5400c042012-02-21 16:40:33 +02004299 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004300 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004301 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004302
4303 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004304 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004305 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004306
4307 hci_dev_lock(hdev);
4308
Johan Hedberg05cbf292013-03-15 17:07:07 -05004309 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4310 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4311 MGMT_STATUS_BUSY);
4312 goto unlock;
4313 }
4314
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004315 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4316 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4317 hdev);
4318 goto unlock;
4319 }
4320
Johan Hedberg33e38b32013-03-15 17:07:05 -05004321 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4322 data, len);
4323 if (!cmd) {
4324 err = -ENOMEM;
4325 goto unlock;
4326 }
4327
4328 hci_req_init(&req, hdev);
4329
Johan Hedberg406d7802013-03-15 17:07:09 -05004330 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004331
4332 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004333 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004334 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004335 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004336 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004337 }
4338
Johan Hedberg33e38b32013-03-15 17:07:05 -05004339unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004340 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004341
Antti Julkuf6422ec2011-06-22 13:11:56 +03004342 return err;
4343}
4344
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004345static void set_bredr_scan(struct hci_request *req)
4346{
4347 struct hci_dev *hdev = req->hdev;
4348 u8 scan = 0;
4349
4350 /* Ensure that fast connectable is disabled. This function will
4351 * not do anything if the page scan parameters are already what
4352 * they should be.
4353 */
4354 write_fast_connectable(req, false);
4355
4356 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4357 scan |= SCAN_PAGE;
4358 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4359 scan |= SCAN_INQUIRY;
4360
4361 if (scan)
4362 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4363}
4364
Johan Hedberg0663ca22013-10-02 13:43:14 +03004365static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4366{
4367 struct pending_cmd *cmd;
4368
4369 BT_DBG("status 0x%02x", status);
4370
4371 hci_dev_lock(hdev);
4372
4373 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4374 if (!cmd)
4375 goto unlock;
4376
4377 if (status) {
4378 u8 mgmt_err = mgmt_status(status);
4379
4380 /* We need to restore the flag if related HCI commands
4381 * failed.
4382 */
4383 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4384
4385 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4386 } else {
4387 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4388 new_settings(hdev, cmd->sk);
4389 }
4390
4391 mgmt_pending_remove(cmd);
4392
4393unlock:
4394 hci_dev_unlock(hdev);
4395}
4396
4397static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4398{
4399 struct mgmt_mode *cp = data;
4400 struct pending_cmd *cmd;
4401 struct hci_request req;
4402 int err;
4403
4404 BT_DBG("request for %s", hdev->name);
4405
4406 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4407 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4408 MGMT_STATUS_NOT_SUPPORTED);
4409
4410 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4411 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4412 MGMT_STATUS_REJECTED);
4413
4414 if (cp->val != 0x00 && cp->val != 0x01)
4415 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4416 MGMT_STATUS_INVALID_PARAMS);
4417
4418 hci_dev_lock(hdev);
4419
4420 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4421 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4422 goto unlock;
4423 }
4424
4425 if (!hdev_is_powered(hdev)) {
4426 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004427 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4428 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4429 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4430 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4431 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4432 }
4433
4434 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4435
4436 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4437 if (err < 0)
4438 goto unlock;
4439
4440 err = new_settings(hdev, sk);
4441 goto unlock;
4442 }
4443
4444 /* Reject disabling when powered on */
4445 if (!cp->val) {
4446 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4447 MGMT_STATUS_REJECTED);
4448 goto unlock;
4449 }
4450
4451 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4452 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4453 MGMT_STATUS_BUSY);
4454 goto unlock;
4455 }
4456
4457 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4458 if (!cmd) {
4459 err = -ENOMEM;
4460 goto unlock;
4461 }
4462
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004463 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004464 * generates the correct flags.
4465 */
4466 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4467
4468 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004469
4470 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4471 set_bredr_scan(&req);
4472
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004473 /* Since only the advertising data flags will change, there
4474 * is no need to update the scan response data.
4475 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004476 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004477
Johan Hedberg0663ca22013-10-02 13:43:14 +03004478 err = hci_req_run(&req, set_bredr_complete);
4479 if (err < 0)
4480 mgmt_pending_remove(cmd);
4481
4482unlock:
4483 hci_dev_unlock(hdev);
4484 return err;
4485}
4486
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004487static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4488 void *data, u16 len)
4489{
4490 struct mgmt_mode *cp = data;
4491 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004492 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004493 int err;
4494
4495 BT_DBG("request for %s", hdev->name);
4496
4497 status = mgmt_bredr_support(hdev);
4498 if (status)
4499 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4500 status);
4501
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004502 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004503 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004504 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4505 MGMT_STATUS_NOT_SUPPORTED);
4506
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004507 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004508 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4509 MGMT_STATUS_INVALID_PARAMS);
4510
4511 hci_dev_lock(hdev);
4512
4513 if (!hdev_is_powered(hdev)) {
4514 bool changed;
4515
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004516 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004517 changed = !test_and_set_bit(HCI_SC_ENABLED,
4518 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004519 if (cp->val == 0x02)
4520 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4521 else
4522 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4523 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004524 changed = test_and_clear_bit(HCI_SC_ENABLED,
4525 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004526 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4527 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004528
4529 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4530 if (err < 0)
4531 goto failed;
4532
4533 if (changed)
4534 err = new_settings(hdev, sk);
4535
4536 goto failed;
4537 }
4538
4539 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4540 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4541 MGMT_STATUS_BUSY);
4542 goto failed;
4543 }
4544
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004545 val = !!cp->val;
4546
4547 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4548 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004549 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4550 goto failed;
4551 }
4552
4553 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4554 if (!cmd) {
4555 err = -ENOMEM;
4556 goto failed;
4557 }
4558
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004559 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004560 if (err < 0) {
4561 mgmt_pending_remove(cmd);
4562 goto failed;
4563 }
4564
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004565 if (cp->val == 0x02)
4566 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4567 else
4568 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4569
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004570failed:
4571 hci_dev_unlock(hdev);
4572 return err;
4573}
4574
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004575static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4576 void *data, u16 len)
4577{
4578 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004579 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004580 int err;
4581
4582 BT_DBG("request for %s", hdev->name);
4583
Johan Hedbergb97109792014-06-24 14:00:28 +03004584 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004585 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4586 MGMT_STATUS_INVALID_PARAMS);
4587
4588 hci_dev_lock(hdev);
4589
4590 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004591 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4592 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004593 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004594 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4595 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004596
Johan Hedbergb97109792014-06-24 14:00:28 +03004597 if (cp->val == 0x02)
4598 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4599 &hdev->dev_flags);
4600 else
4601 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4602 &hdev->dev_flags);
4603
4604 if (hdev_is_powered(hdev) && use_changed &&
4605 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4606 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4607 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4608 sizeof(mode), &mode);
4609 }
4610
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004611 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4612 if (err < 0)
4613 goto unlock;
4614
4615 if (changed)
4616 err = new_settings(hdev, sk);
4617
4618unlock:
4619 hci_dev_unlock(hdev);
4620 return err;
4621}
4622
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004623static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4624 u16 len)
4625{
4626 struct mgmt_cp_set_privacy *cp = cp_data;
4627 bool changed;
4628 int err;
4629
4630 BT_DBG("request for %s", hdev->name);
4631
4632 if (!lmp_le_capable(hdev))
4633 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4634 MGMT_STATUS_NOT_SUPPORTED);
4635
4636 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4637 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4638 MGMT_STATUS_INVALID_PARAMS);
4639
4640 if (hdev_is_powered(hdev))
4641 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4642 MGMT_STATUS_REJECTED);
4643
4644 hci_dev_lock(hdev);
4645
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004646 /* If user space supports this command it is also expected to
4647 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4648 */
4649 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4650
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004651 if (cp->privacy) {
4652 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4653 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4654 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4655 } else {
4656 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4657 memset(hdev->irk, 0, sizeof(hdev->irk));
4658 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4659 }
4660
4661 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4662 if (err < 0)
4663 goto unlock;
4664
4665 if (changed)
4666 err = new_settings(hdev, sk);
4667
4668unlock:
4669 hci_dev_unlock(hdev);
4670 return err;
4671}
4672
Johan Hedberg41edf162014-02-18 10:19:35 +02004673static bool irk_is_valid(struct mgmt_irk_info *irk)
4674{
4675 switch (irk->addr.type) {
4676 case BDADDR_LE_PUBLIC:
4677 return true;
4678
4679 case BDADDR_LE_RANDOM:
4680 /* Two most significant bits shall be set */
4681 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4682 return false;
4683 return true;
4684 }
4685
4686 return false;
4687}
4688
4689static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4690 u16 len)
4691{
4692 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004693 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4694 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004695 u16 irk_count, expected_len;
4696 int i, err;
4697
4698 BT_DBG("request for %s", hdev->name);
4699
4700 if (!lmp_le_capable(hdev))
4701 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4702 MGMT_STATUS_NOT_SUPPORTED);
4703
4704 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004705 if (irk_count > max_irk_count) {
4706 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4707 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4708 MGMT_STATUS_INVALID_PARAMS);
4709 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004710
4711 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4712 if (expected_len != len) {
4713 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004714 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004715 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4716 MGMT_STATUS_INVALID_PARAMS);
4717 }
4718
4719 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4720
4721 for (i = 0; i < irk_count; i++) {
4722 struct mgmt_irk_info *key = &cp->irks[i];
4723
4724 if (!irk_is_valid(key))
4725 return cmd_status(sk, hdev->id,
4726 MGMT_OP_LOAD_IRKS,
4727 MGMT_STATUS_INVALID_PARAMS);
4728 }
4729
4730 hci_dev_lock(hdev);
4731
4732 hci_smp_irks_clear(hdev);
4733
4734 for (i = 0; i < irk_count; i++) {
4735 struct mgmt_irk_info *irk = &cp->irks[i];
4736 u8 addr_type;
4737
4738 if (irk->addr.type == BDADDR_LE_PUBLIC)
4739 addr_type = ADDR_LE_DEV_PUBLIC;
4740 else
4741 addr_type = ADDR_LE_DEV_RANDOM;
4742
4743 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4744 BDADDR_ANY);
4745 }
4746
4747 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4748
4749 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4750
4751 hci_dev_unlock(hdev);
4752
4753 return err;
4754}
4755
Johan Hedberg3f706b72013-01-20 14:27:16 +02004756static bool ltk_is_valid(struct mgmt_ltk_info *key)
4757{
4758 if (key->master != 0x00 && key->master != 0x01)
4759 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004760
4761 switch (key->addr.type) {
4762 case BDADDR_LE_PUBLIC:
4763 return true;
4764
4765 case BDADDR_LE_RANDOM:
4766 /* Two most significant bits shall be set */
4767 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4768 return false;
4769 return true;
4770 }
4771
4772 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004773}
4774
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004775static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004776 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004777{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004778 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004779 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4780 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004781 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004782 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004783
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004784 BT_DBG("request for %s", hdev->name);
4785
4786 if (!lmp_le_capable(hdev))
4787 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4788 MGMT_STATUS_NOT_SUPPORTED);
4789
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004790 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004791 if (key_count > max_key_count) {
4792 BT_ERR("load_ltks: too big key_count value %u", key_count);
4793 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4794 MGMT_STATUS_INVALID_PARAMS);
4795 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004796
4797 expected_len = sizeof(*cp) + key_count *
4798 sizeof(struct mgmt_ltk_info);
4799 if (expected_len != len) {
4800 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004801 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004802 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004803 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004804 }
4805
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004806 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004807
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004808 for (i = 0; i < key_count; i++) {
4809 struct mgmt_ltk_info *key = &cp->keys[i];
4810
Johan Hedberg3f706b72013-01-20 14:27:16 +02004811 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004812 return cmd_status(sk, hdev->id,
4813 MGMT_OP_LOAD_LONG_TERM_KEYS,
4814 MGMT_STATUS_INVALID_PARAMS);
4815 }
4816
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004817 hci_dev_lock(hdev);
4818
4819 hci_smp_ltks_clear(hdev);
4820
4821 for (i = 0; i < key_count; i++) {
4822 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004823 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004824
4825 if (key->addr.type == BDADDR_LE_PUBLIC)
4826 addr_type = ADDR_LE_DEV_PUBLIC;
4827 else
4828 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004829
4830 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004831 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004832 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004833 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004834
Johan Hedberg61b43352014-05-29 19:36:53 +03004835 switch (key->type) {
4836 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004837 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004838 break;
4839 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004840 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004841 break;
4842 default:
4843 continue;
4844 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004845
Johan Hedberg35d70272014-02-19 14:57:47 +02004846 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004847 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004848 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004849 }
4850
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004851 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4852 NULL, 0);
4853
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004854 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004855
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004856 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004857}
4858
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004859struct cmd_conn_lookup {
4860 struct hci_conn *conn;
4861 bool valid_tx_power;
4862 u8 mgmt_status;
4863};
4864
4865static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4866{
4867 struct cmd_conn_lookup *match = data;
4868 struct mgmt_cp_get_conn_info *cp;
4869 struct mgmt_rp_get_conn_info rp;
4870 struct hci_conn *conn = cmd->user_data;
4871
4872 if (conn != match->conn)
4873 return;
4874
4875 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4876
4877 memset(&rp, 0, sizeof(rp));
4878 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4879 rp.addr.type = cp->addr.type;
4880
4881 if (!match->mgmt_status) {
4882 rp.rssi = conn->rssi;
4883
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004884 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004885 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004886 rp.max_tx_power = conn->max_tx_power;
4887 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004888 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004889 rp.max_tx_power = HCI_TX_POWER_INVALID;
4890 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004891 }
4892
4893 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4894 match->mgmt_status, &rp, sizeof(rp));
4895
4896 hci_conn_drop(conn);
4897
4898 mgmt_pending_remove(cmd);
4899}
4900
4901static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4902{
4903 struct hci_cp_read_rssi *cp;
4904 struct hci_conn *conn;
4905 struct cmd_conn_lookup match;
4906 u16 handle;
4907
4908 BT_DBG("status 0x%02x", status);
4909
4910 hci_dev_lock(hdev);
4911
4912 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004913 * otherwise we assume it's not valid. At the moment we assume that
4914 * either both or none of current and max values are valid to keep code
4915 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004916 */
4917 match.valid_tx_power = !status;
4918
4919 /* Commands sent in request are either Read RSSI or Read Transmit Power
4920 * Level so we check which one was last sent to retrieve connection
4921 * handle. Both commands have handle as first parameter so it's safe to
4922 * cast data on the same command struct.
4923 *
4924 * First command sent is always Read RSSI and we fail only if it fails.
4925 * In other case we simply override error to indicate success as we
4926 * already remembered if TX power value is actually valid.
4927 */
4928 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4929 if (!cp) {
4930 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4931 status = 0;
4932 }
4933
4934 if (!cp) {
4935 BT_ERR("invalid sent_cmd in response");
4936 goto unlock;
4937 }
4938
4939 handle = __le16_to_cpu(cp->handle);
4940 conn = hci_conn_hash_lookup_handle(hdev, handle);
4941 if (!conn) {
4942 BT_ERR("unknown handle (%d) in response", handle);
4943 goto unlock;
4944 }
4945
4946 match.conn = conn;
4947 match.mgmt_status = mgmt_status(status);
4948
4949 /* Cache refresh is complete, now reply for mgmt request for given
4950 * connection only.
4951 */
4952 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4953 get_conn_info_complete, &match);
4954
4955unlock:
4956 hci_dev_unlock(hdev);
4957}
4958
4959static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4960 u16 len)
4961{
4962 struct mgmt_cp_get_conn_info *cp = data;
4963 struct mgmt_rp_get_conn_info rp;
4964 struct hci_conn *conn;
4965 unsigned long conn_info_age;
4966 int err = 0;
4967
4968 BT_DBG("%s", hdev->name);
4969
4970 memset(&rp, 0, sizeof(rp));
4971 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4972 rp.addr.type = cp->addr.type;
4973
4974 if (!bdaddr_type_is_valid(cp->addr.type))
4975 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4976 MGMT_STATUS_INVALID_PARAMS,
4977 &rp, sizeof(rp));
4978
4979 hci_dev_lock(hdev);
4980
4981 if (!hdev_is_powered(hdev)) {
4982 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4983 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4984 goto unlock;
4985 }
4986
4987 if (cp->addr.type == BDADDR_BREDR)
4988 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4989 &cp->addr.bdaddr);
4990 else
4991 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4992
4993 if (!conn || conn->state != BT_CONNECTED) {
4994 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4995 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4996 goto unlock;
4997 }
4998
4999 /* To avoid client trying to guess when to poll again for information we
5000 * calculate conn info age as random value between min/max set in hdev.
5001 */
5002 conn_info_age = hdev->conn_info_min_age +
5003 prandom_u32_max(hdev->conn_info_max_age -
5004 hdev->conn_info_min_age);
5005
5006 /* Query controller to refresh cached values if they are too old or were
5007 * never read.
5008 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005009 if (time_after(jiffies, conn->conn_info_timestamp +
5010 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005011 !conn->conn_info_timestamp) {
5012 struct hci_request req;
5013 struct hci_cp_read_tx_power req_txp_cp;
5014 struct hci_cp_read_rssi req_rssi_cp;
5015 struct pending_cmd *cmd;
5016
5017 hci_req_init(&req, hdev);
5018 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5019 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5020 &req_rssi_cp);
5021
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005022 /* For LE links TX power does not change thus we don't need to
5023 * query for it once value is known.
5024 */
5025 if (!bdaddr_type_is_le(cp->addr.type) ||
5026 conn->tx_power == HCI_TX_POWER_INVALID) {
5027 req_txp_cp.handle = cpu_to_le16(conn->handle);
5028 req_txp_cp.type = 0x00;
5029 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5030 sizeof(req_txp_cp), &req_txp_cp);
5031 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005032
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005033 /* Max TX power needs to be read only once per connection */
5034 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5035 req_txp_cp.handle = cpu_to_le16(conn->handle);
5036 req_txp_cp.type = 0x01;
5037 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5038 sizeof(req_txp_cp), &req_txp_cp);
5039 }
5040
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005041 err = hci_req_run(&req, conn_info_refresh_complete);
5042 if (err < 0)
5043 goto unlock;
5044
5045 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5046 data, len);
5047 if (!cmd) {
5048 err = -ENOMEM;
5049 goto unlock;
5050 }
5051
5052 hci_conn_hold(conn);
5053 cmd->user_data = conn;
5054
5055 conn->conn_info_timestamp = jiffies;
5056 } else {
5057 /* Cache is valid, just reply with values cached in hci_conn */
5058 rp.rssi = conn->rssi;
5059 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005060 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005061
5062 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5063 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5064 }
5065
5066unlock:
5067 hci_dev_unlock(hdev);
5068 return err;
5069}
5070
Johan Hedberg95868422014-06-28 17:54:07 +03005071static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5072{
5073 struct mgmt_cp_get_clock_info *cp;
5074 struct mgmt_rp_get_clock_info rp;
5075 struct hci_cp_read_clock *hci_cp;
5076 struct pending_cmd *cmd;
5077 struct hci_conn *conn;
5078
5079 BT_DBG("%s status %u", hdev->name, status);
5080
5081 hci_dev_lock(hdev);
5082
5083 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5084 if (!hci_cp)
5085 goto unlock;
5086
5087 if (hci_cp->which) {
5088 u16 handle = __le16_to_cpu(hci_cp->handle);
5089 conn = hci_conn_hash_lookup_handle(hdev, handle);
5090 } else {
5091 conn = NULL;
5092 }
5093
5094 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5095 if (!cmd)
5096 goto unlock;
5097
5098 cp = cmd->param;
5099
5100 memset(&rp, 0, sizeof(rp));
5101 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5102
5103 if (status)
5104 goto send_rsp;
5105
5106 rp.local_clock = cpu_to_le32(hdev->clock);
5107
5108 if (conn) {
5109 rp.piconet_clock = cpu_to_le32(conn->clock);
5110 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5111 }
5112
5113send_rsp:
5114 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5115 &rp, sizeof(rp));
5116 mgmt_pending_remove(cmd);
5117 if (conn)
5118 hci_conn_drop(conn);
5119
5120unlock:
5121 hci_dev_unlock(hdev);
5122}
5123
5124static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5125 u16 len)
5126{
5127 struct mgmt_cp_get_clock_info *cp = data;
5128 struct mgmt_rp_get_clock_info rp;
5129 struct hci_cp_read_clock hci_cp;
5130 struct pending_cmd *cmd;
5131 struct hci_request req;
5132 struct hci_conn *conn;
5133 int err;
5134
5135 BT_DBG("%s", hdev->name);
5136
5137 memset(&rp, 0, sizeof(rp));
5138 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5139 rp.addr.type = cp->addr.type;
5140
5141 if (cp->addr.type != BDADDR_BREDR)
5142 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5143 MGMT_STATUS_INVALID_PARAMS,
5144 &rp, sizeof(rp));
5145
5146 hci_dev_lock(hdev);
5147
5148 if (!hdev_is_powered(hdev)) {
5149 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5150 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5151 goto unlock;
5152 }
5153
5154 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5155 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5156 &cp->addr.bdaddr);
5157 if (!conn || conn->state != BT_CONNECTED) {
5158 err = cmd_complete(sk, hdev->id,
5159 MGMT_OP_GET_CLOCK_INFO,
5160 MGMT_STATUS_NOT_CONNECTED,
5161 &rp, sizeof(rp));
5162 goto unlock;
5163 }
5164 } else {
5165 conn = NULL;
5166 }
5167
5168 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5169 if (!cmd) {
5170 err = -ENOMEM;
5171 goto unlock;
5172 }
5173
5174 hci_req_init(&req, hdev);
5175
5176 memset(&hci_cp, 0, sizeof(hci_cp));
5177 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5178
5179 if (conn) {
5180 hci_conn_hold(conn);
5181 cmd->user_data = conn;
5182
5183 hci_cp.handle = cpu_to_le16(conn->handle);
5184 hci_cp.which = 0x01; /* Piconet clock */
5185 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5186 }
5187
5188 err = hci_req_run(&req, get_clock_info_complete);
5189 if (err < 0)
5190 mgmt_pending_remove(cmd);
5191
5192unlock:
5193 hci_dev_unlock(hdev);
5194 return err;
5195}
5196
Marcel Holtmann8afef092014-06-29 22:28:34 +02005197static void device_added(struct sock *sk, struct hci_dev *hdev,
5198 bdaddr_t *bdaddr, u8 type, u8 action)
5199{
5200 struct mgmt_ev_device_added ev;
5201
5202 bacpy(&ev.addr.bdaddr, bdaddr);
5203 ev.addr.type = type;
5204 ev.action = action;
5205
5206 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5207}
5208
Marcel Holtmann2faade52014-06-29 19:44:03 +02005209static int add_device(struct sock *sk, struct hci_dev *hdev,
5210 void *data, u16 len)
5211{
5212 struct mgmt_cp_add_device *cp = data;
5213 u8 auto_conn, addr_type;
5214 int err;
5215
5216 BT_DBG("%s", hdev->name);
5217
5218 if (!bdaddr_type_is_le(cp->addr.type) ||
5219 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5220 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5221 MGMT_STATUS_INVALID_PARAMS,
5222 &cp->addr, sizeof(cp->addr));
5223
5224 if (cp->action != 0x00 && cp->action != 0x01)
5225 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5226 MGMT_STATUS_INVALID_PARAMS,
5227 &cp->addr, sizeof(cp->addr));
5228
5229 hci_dev_lock(hdev);
5230
5231 if (cp->addr.type == BDADDR_LE_PUBLIC)
5232 addr_type = ADDR_LE_DEV_PUBLIC;
5233 else
5234 addr_type = ADDR_LE_DEV_RANDOM;
5235
5236 if (cp->action)
5237 auto_conn = HCI_AUTO_CONN_ALWAYS;
5238 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005239 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005240
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005241 /* If the connection parameters don't exist for this device,
5242 * they will be created and configured with defaults.
5243 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005244 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5245 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005246 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5247 MGMT_STATUS_FAILED,
5248 &cp->addr, sizeof(cp->addr));
5249 goto unlock;
5250 }
5251
Marcel Holtmann8afef092014-06-29 22:28:34 +02005252 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5253
Marcel Holtmann2faade52014-06-29 19:44:03 +02005254 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5255 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5256
5257unlock:
5258 hci_dev_unlock(hdev);
5259 return err;
5260}
5261
Marcel Holtmann8afef092014-06-29 22:28:34 +02005262static void device_removed(struct sock *sk, struct hci_dev *hdev,
5263 bdaddr_t *bdaddr, u8 type)
5264{
5265 struct mgmt_ev_device_removed ev;
5266
5267 bacpy(&ev.addr.bdaddr, bdaddr);
5268 ev.addr.type = type;
5269
5270 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5271}
5272
Marcel Holtmann2faade52014-06-29 19:44:03 +02005273static int remove_device(struct sock *sk, struct hci_dev *hdev,
5274 void *data, u16 len)
5275{
5276 struct mgmt_cp_remove_device *cp = data;
5277 int err;
5278
5279 BT_DBG("%s", hdev->name);
5280
5281 hci_dev_lock(hdev);
5282
5283 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005284 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005285 u8 addr_type;
5286
5287 if (!bdaddr_type_is_le(cp->addr.type)) {
5288 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5289 MGMT_STATUS_INVALID_PARAMS,
5290 &cp->addr, sizeof(cp->addr));
5291 goto unlock;
5292 }
5293
5294 if (cp->addr.type == BDADDR_LE_PUBLIC)
5295 addr_type = ADDR_LE_DEV_PUBLIC;
5296 else
5297 addr_type = ADDR_LE_DEV_RANDOM;
5298
Johan Hedbergc71593d2014-07-02 17:37:28 +03005299 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5300 addr_type);
5301 if (!params) {
5302 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5303 MGMT_STATUS_INVALID_PARAMS,
5304 &cp->addr, sizeof(cp->addr));
5305 goto unlock;
5306 }
5307
5308 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5309 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5310 MGMT_STATUS_INVALID_PARAMS,
5311 &cp->addr, sizeof(cp->addr));
5312 goto unlock;
5313 }
5314
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005315 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005316 list_del(&params->list);
5317 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005318 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005319
5320 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005321 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005322 struct hci_conn_params *p, *tmp;
5323
Marcel Holtmann2faade52014-06-29 19:44:03 +02005324 if (cp->addr.type) {
5325 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5326 MGMT_STATUS_INVALID_PARAMS,
5327 &cp->addr, sizeof(cp->addr));
5328 goto unlock;
5329 }
5330
Johan Hedberg19de0822014-07-06 13:06:51 +03005331 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5332 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5333 continue;
5334 device_removed(sk, hdev, &p->addr, p->addr_type);
5335 list_del(&p->action);
5336 list_del(&p->list);
5337 kfree(p);
5338 }
5339
5340 BT_DBG("All LE connection parameters were removed");
5341
5342 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005343 }
5344
5345 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5346 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5347
5348unlock:
5349 hci_dev_unlock(hdev);
5350 return err;
5351}
5352
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005353static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5354 u16 len)
5355{
5356 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005357 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5358 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005359 u16 param_count, expected_len;
5360 int i;
5361
5362 if (!lmp_le_capable(hdev))
5363 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5364 MGMT_STATUS_NOT_SUPPORTED);
5365
5366 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005367 if (param_count > max_param_count) {
5368 BT_ERR("load_conn_param: too big param_count value %u",
5369 param_count);
5370 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5371 MGMT_STATUS_INVALID_PARAMS);
5372 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005373
5374 expected_len = sizeof(*cp) + param_count *
5375 sizeof(struct mgmt_conn_param);
5376 if (expected_len != len) {
5377 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5378 expected_len, len);
5379 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5380 MGMT_STATUS_INVALID_PARAMS);
5381 }
5382
5383 BT_DBG("%s param_count %u", hdev->name, param_count);
5384
5385 hci_dev_lock(hdev);
5386
5387 hci_conn_params_clear_disabled(hdev);
5388
5389 for (i = 0; i < param_count; i++) {
5390 struct mgmt_conn_param *param = &cp->params[i];
5391 struct hci_conn_params *hci_param;
5392 u16 min, max, latency, timeout;
5393 u8 addr_type;
5394
5395 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5396 param->addr.type);
5397
5398 if (param->addr.type == BDADDR_LE_PUBLIC) {
5399 addr_type = ADDR_LE_DEV_PUBLIC;
5400 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5401 addr_type = ADDR_LE_DEV_RANDOM;
5402 } else {
5403 BT_ERR("Ignoring invalid connection parameters");
5404 continue;
5405 }
5406
5407 min = le16_to_cpu(param->min_interval);
5408 max = le16_to_cpu(param->max_interval);
5409 latency = le16_to_cpu(param->latency);
5410 timeout = le16_to_cpu(param->timeout);
5411
5412 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5413 min, max, latency, timeout);
5414
5415 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5416 BT_ERR("Ignoring invalid connection parameters");
5417 continue;
5418 }
5419
5420 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5421 addr_type);
5422 if (!hci_param) {
5423 BT_ERR("Failed to add connection parameters");
5424 continue;
5425 }
5426
5427 hci_param->conn_min_interval = min;
5428 hci_param->conn_max_interval = max;
5429 hci_param->conn_latency = latency;
5430 hci_param->supervision_timeout = timeout;
5431 }
5432
5433 hci_dev_unlock(hdev);
5434
5435 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5436}
5437
Marcel Holtmanndbece372014-07-04 18:11:55 +02005438static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5439 void *data, u16 len)
5440{
5441 struct mgmt_cp_set_external_config *cp = data;
5442 bool changed;
5443 int err;
5444
5445 BT_DBG("%s", hdev->name);
5446
5447 if (hdev_is_powered(hdev))
5448 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5449 MGMT_STATUS_REJECTED);
5450
5451 if (cp->config != 0x00 && cp->config != 0x01)
5452 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5453 MGMT_STATUS_INVALID_PARAMS);
5454
5455 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5456 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5457 MGMT_STATUS_NOT_SUPPORTED);
5458
5459 hci_dev_lock(hdev);
5460
5461 if (cp->config)
5462 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5463 &hdev->dev_flags);
5464 else
5465 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5466 &hdev->dev_flags);
5467
5468 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5469 if (err < 0)
5470 goto unlock;
5471
5472 if (!changed)
5473 goto unlock;
5474
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005475 err = new_options(hdev, sk);
5476
Marcel Holtmanndbece372014-07-04 18:11:55 +02005477 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5478 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005479
5480 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5481 set_bit(HCI_CONFIG, &hdev->dev_flags);
5482 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5483
5484 queue_work(hdev->req_workqueue, &hdev->power_on);
5485 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005486 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005487 mgmt_index_added(hdev);
5488 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005489 }
5490
5491unlock:
5492 hci_dev_unlock(hdev);
5493 return err;
5494}
5495
Marcel Holtmann9713c172014-07-06 12:11:15 +02005496static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5497 void *data, u16 len)
5498{
5499 struct mgmt_cp_set_public_address *cp = data;
5500 bool changed;
5501 int err;
5502
5503 BT_DBG("%s", hdev->name);
5504
5505 if (hdev_is_powered(hdev))
5506 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5507 MGMT_STATUS_REJECTED);
5508
5509 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5510 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5511 MGMT_STATUS_INVALID_PARAMS);
5512
5513 if (!hdev->set_bdaddr)
5514 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5515 MGMT_STATUS_NOT_SUPPORTED);
5516
5517 hci_dev_lock(hdev);
5518
5519 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5520 bacpy(&hdev->public_addr, &cp->bdaddr);
5521
5522 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5523 if (err < 0)
5524 goto unlock;
5525
5526 if (!changed)
5527 goto unlock;
5528
5529 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5530 err = new_options(hdev, sk);
5531
5532 if (is_configured(hdev)) {
5533 mgmt_index_removed(hdev);
5534
5535 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5536
5537 set_bit(HCI_CONFIG, &hdev->dev_flags);
5538 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5539
5540 queue_work(hdev->req_workqueue, &hdev->power_on);
5541 }
5542
5543unlock:
5544 hci_dev_unlock(hdev);
5545 return err;
5546}
5547
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005548static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005549 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5550 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005551 bool var_len;
5552 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005553} mgmt_handlers[] = {
5554 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005555 { read_version, false, MGMT_READ_VERSION_SIZE },
5556 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5557 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5558 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5559 { set_powered, false, MGMT_SETTING_SIZE },
5560 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5561 { set_connectable, false, MGMT_SETTING_SIZE },
5562 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5563 { set_pairable, false, MGMT_SETTING_SIZE },
5564 { set_link_security, false, MGMT_SETTING_SIZE },
5565 { set_ssp, false, MGMT_SETTING_SIZE },
5566 { set_hs, false, MGMT_SETTING_SIZE },
5567 { set_le, false, MGMT_SETTING_SIZE },
5568 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5569 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5570 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5571 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5572 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5573 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5574 { disconnect, false, MGMT_DISCONNECT_SIZE },
5575 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5576 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5577 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5578 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5579 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5580 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5581 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5582 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5583 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5584 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5585 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5586 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005587 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005588 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5589 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5590 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5591 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5592 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5593 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005594 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005595 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005596 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005597 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005598 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005599 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005600 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005601 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005602 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005603 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005604 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005605 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5606 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005607 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5608 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005609 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005610 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005611 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005612};
5613
Johan Hedberg03811012010-12-08 00:21:06 +02005614int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5615{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005616 void *buf;
5617 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005618 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005619 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005620 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005621 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005622 int err;
5623
5624 BT_DBG("got %zu bytes", msglen);
5625
5626 if (msglen < sizeof(*hdr))
5627 return -EINVAL;
5628
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005629 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005630 if (!buf)
5631 return -ENOMEM;
5632
5633 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5634 err = -EFAULT;
5635 goto done;
5636 }
5637
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005638 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005639 opcode = __le16_to_cpu(hdr->opcode);
5640 index = __le16_to_cpu(hdr->index);
5641 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005642
5643 if (len != msglen - sizeof(*hdr)) {
5644 err = -EINVAL;
5645 goto done;
5646 }
5647
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005648 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005649 hdev = hci_dev_get(index);
5650 if (!hdev) {
5651 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005652 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005653 goto done;
5654 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005655
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005656 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005657 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005658 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005659 err = cmd_status(sk, index, opcode,
5660 MGMT_STATUS_INVALID_INDEX);
5661 goto done;
5662 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005663
5664 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005665 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005666 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5667 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005668 err = cmd_status(sk, index, opcode,
5669 MGMT_STATUS_INVALID_INDEX);
5670 goto done;
5671 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005672 }
5673
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005674 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005675 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005676 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005677 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005678 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005679 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005680 }
5681
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005682 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5683 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5684 err = cmd_status(sk, index, opcode,
5685 MGMT_STATUS_INVALID_INDEX);
5686 goto done;
5687 }
5688
5689 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5690 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005691 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005692 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005693 goto done;
5694 }
5695
Johan Hedbergbe22b542012-03-01 22:24:41 +02005696 handler = &mgmt_handlers[opcode];
5697
5698 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005699 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005700 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005701 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005702 goto done;
5703 }
5704
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005705 if (hdev)
5706 mgmt_init_hdev(sk, hdev);
5707
5708 cp = buf + sizeof(*hdr);
5709
Johan Hedbergbe22b542012-03-01 22:24:41 +02005710 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005711 if (err < 0)
5712 goto done;
5713
Johan Hedberg03811012010-12-08 00:21:06 +02005714 err = msglen;
5715
5716done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005717 if (hdev)
5718 hci_dev_put(hdev);
5719
Johan Hedberg03811012010-12-08 00:21:06 +02005720 kfree(buf);
5721 return err;
5722}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005723
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005724void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005725{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005726 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005727 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005728
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005729 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5730 return;
5731
5732 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5733 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5734 else
5735 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005736}
5737
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005738void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005739{
Johan Hedberg5f159032012-03-02 03:13:19 +02005740 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005741
Marcel Holtmann1514b892013-10-06 08:25:01 -07005742 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005743 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005744
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005745 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5746 return;
5747
Johan Hedberg744cf192011-11-08 20:40:14 +02005748 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005749
Marcel Holtmannedd38962014-07-02 21:30:55 +02005750 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5751 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5752 else
5753 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005754}
5755
Andre Guedes6046dc32014-02-26 20:21:51 -03005756/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005757static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005758{
5759 struct hci_conn_params *p;
5760
5761 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005762 /* Needed for AUTO_OFF case where might not "really"
5763 * have been powered off.
5764 */
5765 list_del_init(&p->action);
5766
5767 switch (p->auto_connect) {
5768 case HCI_AUTO_CONN_ALWAYS:
5769 list_add(&p->action, &hdev->pend_le_conns);
5770 break;
5771 case HCI_AUTO_CONN_REPORT:
5772 list_add(&p->action, &hdev->pend_le_reports);
5773 break;
5774 default:
5775 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005776 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005777 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005778
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005779 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005780}
5781
Johan Hedberg229ab392013-03-15 17:06:53 -05005782static void powered_complete(struct hci_dev *hdev, u8 status)
5783{
5784 struct cmd_lookup match = { NULL, hdev };
5785
5786 BT_DBG("status 0x%02x", status);
5787
5788 hci_dev_lock(hdev);
5789
Johan Hedbergd7347f32014-07-04 12:37:23 +03005790 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005791
Johan Hedberg229ab392013-03-15 17:06:53 -05005792 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5793
5794 new_settings(hdev, match.sk);
5795
5796 hci_dev_unlock(hdev);
5797
5798 if (match.sk)
5799 sock_put(match.sk);
5800}
5801
Johan Hedberg70da6242013-03-15 17:06:51 -05005802static int powered_update_hci(struct hci_dev *hdev)
5803{
Johan Hedberg890ea892013-03-15 17:06:52 -05005804 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005805 u8 link_sec;
5806
Johan Hedberg890ea892013-03-15 17:06:52 -05005807 hci_req_init(&req, hdev);
5808
Johan Hedberg70da6242013-03-15 17:06:51 -05005809 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5810 !lmp_host_ssp_capable(hdev)) {
5811 u8 ssp = 1;
5812
Johan Hedberg890ea892013-03-15 17:06:52 -05005813 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005814 }
5815
Johan Hedbergc73eee92013-04-19 18:35:21 +03005816 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5817 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005818 struct hci_cp_write_le_host_supported cp;
5819
5820 cp.le = 1;
5821 cp.simul = lmp_le_br_capable(hdev);
5822
5823 /* Check first if we already have the right
5824 * host state (host features set)
5825 */
5826 if (cp.le != lmp_host_le_capable(hdev) ||
5827 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005828 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5829 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005830 }
5831
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005832 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005833 /* Make sure the controller has a good default for
5834 * advertising data. This also applies to the case
5835 * where BR/EDR was toggled during the AUTO_OFF phase.
5836 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005837 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005838 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005839 update_scan_rsp_data(&req);
5840 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005841
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005842 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5843 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005844 }
5845
Johan Hedberg70da6242013-03-15 17:06:51 -05005846 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5847 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005848 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5849 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005850
5851 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005852 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5853 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005854 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005855 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005856 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005857 }
5858
Johan Hedberg229ab392013-03-15 17:06:53 -05005859 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005860}
5861
Johan Hedberg744cf192011-11-08 20:40:14 +02005862int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005863{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005864 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005865 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5866 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005867 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005868
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005869 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5870 return 0;
5871
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005872 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005873 if (powered_update_hci(hdev) == 0)
5874 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005875
Johan Hedberg229ab392013-03-15 17:06:53 -05005876 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5877 &match);
5878 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005879 }
5880
Johan Hedberg229ab392013-03-15 17:06:53 -05005881 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5882 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5883
5884 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5885 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5886 zero_cod, sizeof(zero_cod), NULL);
5887
5888new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005889 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005890
5891 if (match.sk)
5892 sock_put(match.sk);
5893
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005894 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005895}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005896
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005897void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005898{
5899 struct pending_cmd *cmd;
5900 u8 status;
5901
5902 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5903 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005904 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005905
5906 if (err == -ERFKILL)
5907 status = MGMT_STATUS_RFKILLED;
5908 else
5909 status = MGMT_STATUS_FAILED;
5910
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005911 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005912
5913 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005914}
5915
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005916void mgmt_discoverable_timeout(struct hci_dev *hdev)
5917{
5918 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005919
5920 hci_dev_lock(hdev);
5921
5922 /* When discoverable timeout triggers, then just make sure
5923 * the limited discoverable flag is cleared. Even in the case
5924 * of a timeout triggered from general discoverable, it is
5925 * safe to unconditionally clear the flag.
5926 */
5927 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005928 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005929
5930 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005931 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5932 u8 scan = SCAN_PAGE;
5933 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5934 sizeof(scan), &scan);
5935 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005936 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005937 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005938 hci_req_run(&req, NULL);
5939
5940 hdev->discov_timeout = 0;
5941
Johan Hedberg9a43e252013-10-20 19:00:07 +03005942 new_settings(hdev, NULL);
5943
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005944 hci_dev_unlock(hdev);
5945}
5946
Marcel Holtmann86a75642013-10-15 06:33:54 -07005947void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005948{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005949 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005950
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005951 /* Nothing needed here if there's a pending command since that
5952 * commands request completion callback takes care of everything
5953 * necessary.
5954 */
5955 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005956 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005957
Johan Hedbergbd107992014-02-24 14:52:19 +02005958 /* Powering off may clear the scan mode - don't let that interfere */
5959 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5960 return;
5961
Johan Hedberg9a43e252013-10-20 19:00:07 +03005962 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005963 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005964 } else {
5965 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005966 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005967 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005968
Johan Hedberg9a43e252013-10-20 19:00:07 +03005969 if (changed) {
5970 struct hci_request req;
5971
5972 /* In case this change in discoverable was triggered by
5973 * a disabling of connectable there could be a need to
5974 * update the advertising flags.
5975 */
5976 hci_req_init(&req, hdev);
5977 update_adv_data(&req);
5978 hci_req_run(&req, NULL);
5979
Marcel Holtmann86a75642013-10-15 06:33:54 -07005980 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005981 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005982}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005983
Marcel Holtmanna3309162013-10-15 06:33:55 -07005984void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005985{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005986 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005987
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005988 /* Nothing needed here if there's a pending command since that
5989 * commands request completion callback takes care of everything
5990 * necessary.
5991 */
5992 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005993 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005994
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005995 /* Powering off may clear the scan mode - don't let that interfere */
5996 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5997 return;
5998
Marcel Holtmanna3309162013-10-15 06:33:55 -07005999 if (connectable)
6000 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
6001 else
6002 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006003
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006004 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07006005 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02006006}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006007
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07006008void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006009{
Johan Hedbergca69b792011-11-11 18:10:00 +02006010 u8 mgmt_err = mgmt_status(status);
6011
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006012 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02006013 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006014 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006015
6016 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02006017 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006018 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02006019}
6020
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006021void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6022 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006023{
Johan Hedberg86742e12011-11-07 23:13:38 +02006024 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006025
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006026 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006027
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006028 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006029 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006030 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006031 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006032 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006033 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006034
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006035 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006036}
Johan Hedbergf7520542011-01-20 12:34:39 +02006037
Johan Hedbergd7b25452014-05-23 13:19:53 +03006038static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6039{
6040 if (ltk->authenticated)
6041 return MGMT_LTK_AUTHENTICATED;
6042
6043 return MGMT_LTK_UNAUTHENTICATED;
6044}
6045
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006046void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006047{
6048 struct mgmt_ev_new_long_term_key ev;
6049
6050 memset(&ev, 0, sizeof(ev));
6051
Marcel Holtmann5192d302014-02-19 17:11:58 -08006052 /* Devices using resolvable or non-resolvable random addresses
6053 * without providing an indentity resolving key don't require
6054 * to store long term keys. Their addresses will change the
6055 * next time around.
6056 *
6057 * Only when a remote device provides an identity address
6058 * make sure the long term key is stored. If the remote
6059 * identity is known, the long term keys are internally
6060 * mapped to the identity address. So allow static random
6061 * and public addresses here.
6062 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006063 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6064 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6065 ev.store_hint = 0x00;
6066 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006067 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006068
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006069 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006070 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006071 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006072 ev.key.enc_size = key->enc_size;
6073 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006074 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006075
Johan Hedberg2ceba532014-06-16 19:25:16 +03006076 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006077 ev.key.master = 1;
6078
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006079 memcpy(ev.key.val, key->val, sizeof(key->val));
6080
Marcel Holtmann083368f2013-10-15 14:26:29 -07006081 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006082}
6083
Johan Hedberg95fbac82014-02-19 15:18:31 +02006084void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6085{
6086 struct mgmt_ev_new_irk ev;
6087
6088 memset(&ev, 0, sizeof(ev));
6089
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006090 /* For identity resolving keys from devices that are already
6091 * using a public address or static random address, do not
6092 * ask for storing this key. The identity resolving key really
6093 * is only mandatory for devices using resovlable random
6094 * addresses.
6095 *
6096 * Storing all identity resolving keys has the downside that
6097 * they will be also loaded on next boot of they system. More
6098 * identity resolving keys, means more time during scanning is
6099 * needed to actually resolve these addresses.
6100 */
6101 if (bacmp(&irk->rpa, BDADDR_ANY))
6102 ev.store_hint = 0x01;
6103 else
6104 ev.store_hint = 0x00;
6105
Johan Hedberg95fbac82014-02-19 15:18:31 +02006106 bacpy(&ev.rpa, &irk->rpa);
6107 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6108 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6109 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6110
6111 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6112}
6113
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006114void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6115 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006116{
6117 struct mgmt_ev_new_csrk ev;
6118
6119 memset(&ev, 0, sizeof(ev));
6120
6121 /* Devices using resolvable or non-resolvable random addresses
6122 * without providing an indentity resolving key don't require
6123 * to store signature resolving keys. Their addresses will change
6124 * the next time around.
6125 *
6126 * Only when a remote device provides an identity address
6127 * make sure the signature resolving key is stored. So allow
6128 * static random and public addresses here.
6129 */
6130 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6131 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6132 ev.store_hint = 0x00;
6133 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006134 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006135
6136 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6137 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6138 ev.key.master = csrk->master;
6139 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6140
6141 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6142}
6143
Andre Guedesffb5a8272014-07-01 18:10:11 -03006144void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006145 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6146 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006147{
6148 struct mgmt_ev_new_conn_param ev;
6149
Johan Hedbergc103aea2014-07-02 17:37:34 +03006150 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6151 return;
6152
Andre Guedesffb5a8272014-07-01 18:10:11 -03006153 memset(&ev, 0, sizeof(ev));
6154 bacpy(&ev.addr.bdaddr, bdaddr);
6155 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006156 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006157 ev.min_interval = cpu_to_le16(min_interval);
6158 ev.max_interval = cpu_to_le16(max_interval);
6159 ev.latency = cpu_to_le16(latency);
6160 ev.timeout = cpu_to_le16(timeout);
6161
6162 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6163}
6164
Marcel Holtmann94933992013-10-15 10:26:39 -07006165static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6166 u8 data_len)
6167{
6168 eir[eir_len++] = sizeof(type) + data_len;
6169 eir[eir_len++] = type;
6170 memcpy(&eir[eir_len], data, data_len);
6171 eir_len += data_len;
6172
6173 return eir_len;
6174}
6175
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006176void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6177 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6178 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006179{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006180 char buf[512];
6181 struct mgmt_ev_device_connected *ev = (void *) buf;
6182 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006183
Johan Hedbergb644ba32012-01-17 21:48:47 +02006184 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006185 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006186
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006187 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006188
Johan Hedbergb644ba32012-01-17 21:48:47 +02006189 if (name_len > 0)
6190 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006191 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006192
6193 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006194 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006195 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006196
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006197 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006198
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006199 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6200 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006201}
6202
Johan Hedberg8962ee72011-01-20 12:40:27 +02006203static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6204{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006205 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006206 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006207 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006208
Johan Hedberg88c3df12012-02-09 14:27:38 +02006209 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6210 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006211
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006212 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006213 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006214
6215 *sk = cmd->sk;
6216 sock_hold(*sk);
6217
Johan Hedberga664b5b2011-02-19 12:06:02 -03006218 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006219}
6220
Johan Hedberg124f6e32012-02-09 13:50:12 +02006221static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006222{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006223 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006224 struct mgmt_cp_unpair_device *cp = cmd->param;
6225 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006226
6227 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006228 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6229 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006230
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006231 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6232
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006233 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006234
6235 mgmt_pending_remove(cmd);
6236}
6237
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006238void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006239 u8 link_type, u8 addr_type, u8 reason,
6240 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006241{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006242 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006243 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006244 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006245
Johan Hedberg8b064a32014-02-24 14:52:22 +02006246 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6247 if (power_off) {
6248 struct mgmt_mode *cp = power_off->param;
6249
6250 /* The connection is still in hci_conn_hash so test for 1
6251 * instead of 0 to know if this is the last one.
6252 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006253 if (!cp->val && hci_conn_count(hdev) == 1) {
6254 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006255 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006256 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006257 }
6258
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006259 if (!mgmt_connected)
6260 return;
6261
Andre Guedes57eb7762013-10-30 19:01:41 -03006262 if (link_type != ACL_LINK && link_type != LE_LINK)
6263 return;
6264
Johan Hedberg744cf192011-11-08 20:40:14 +02006265 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006266
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006267 bacpy(&ev.addr.bdaddr, bdaddr);
6268 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6269 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006270
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006271 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006272
6273 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006274 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006275
Johan Hedberg124f6e32012-02-09 13:50:12 +02006276 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006277 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006278}
6279
Marcel Holtmann78929242013-10-06 23:55:47 -07006280void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6281 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006282{
Andre Guedes3655bba2013-10-30 19:01:40 -03006283 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6284 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006285 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006286 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006287
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006288 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6289 hdev);
6290
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006291 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006292 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006293 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006294
Andre Guedes3655bba2013-10-30 19:01:40 -03006295 cp = cmd->param;
6296
6297 if (bacmp(bdaddr, &cp->addr.bdaddr))
6298 return;
6299
6300 if (cp->addr.type != bdaddr_type)
6301 return;
6302
Johan Hedberg88c3df12012-02-09 14:27:38 +02006303 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006304 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006305
Marcel Holtmann78929242013-10-06 23:55:47 -07006306 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6307 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006308
Johan Hedberga664b5b2011-02-19 12:06:02 -03006309 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006310}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006311
Marcel Holtmann445608d2013-10-06 23:55:48 -07006312void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6313 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006314{
6315 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006316 struct pending_cmd *power_off;
6317
6318 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6319 if (power_off) {
6320 struct mgmt_mode *cp = power_off->param;
6321
6322 /* The connection is still in hci_conn_hash so test for 1
6323 * instead of 0 to know if this is the last one.
6324 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006325 if (!cp->val && hci_conn_count(hdev) == 1) {
6326 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006327 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006328 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006329 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006330
Johan Hedberg4c659c32011-11-07 23:13:39 +02006331 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006332 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006333 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006334
Marcel Holtmann445608d2013-10-06 23:55:48 -07006335 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006336}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006337
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006338void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006339{
6340 struct mgmt_ev_pin_code_request ev;
6341
Johan Hedbergd8457692012-02-17 14:24:57 +02006342 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006343 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006344 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006345
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006346 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006347}
6348
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006349void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6350 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006351{
6352 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006353 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006354
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006355 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006356 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006357 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006358
Johan Hedbergd8457692012-02-17 14:24:57 +02006359 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006360 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006361
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006362 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6363 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006364
Johan Hedberga664b5b2011-02-19 12:06:02 -03006365 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006366}
6367
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006368void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6369 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006370{
6371 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006372 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006373
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006374 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006375 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006376 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006377
Johan Hedbergd8457692012-02-17 14:24:57 +02006378 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006379 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006380
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006381 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6382 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006383
Johan Hedberga664b5b2011-02-19 12:06:02 -03006384 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006385}
Johan Hedberga5c29682011-02-19 12:05:57 -03006386
Johan Hedberg744cf192011-11-08 20:40:14 +02006387int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006388 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006389 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006390{
6391 struct mgmt_ev_user_confirm_request ev;
6392
Johan Hedberg744cf192011-11-08 20:40:14 +02006393 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006394
Johan Hedberg272d90d2012-02-09 15:26:12 +02006395 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006396 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006397 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006398 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006399
Johan Hedberg744cf192011-11-08 20:40:14 +02006400 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006401 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006402}
6403
Johan Hedberg272d90d2012-02-09 15:26:12 +02006404int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006405 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006406{
6407 struct mgmt_ev_user_passkey_request ev;
6408
6409 BT_DBG("%s", hdev->name);
6410
Johan Hedberg272d90d2012-02-09 15:26:12 +02006411 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006412 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006413
6414 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006415 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006416}
6417
Brian Gix0df4c182011-11-16 13:53:13 -08006418static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006419 u8 link_type, u8 addr_type, u8 status,
6420 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006421{
6422 struct pending_cmd *cmd;
6423 struct mgmt_rp_user_confirm_reply rp;
6424 int err;
6425
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006426 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006427 if (!cmd)
6428 return -ENOENT;
6429
Johan Hedberg272d90d2012-02-09 15:26:12 +02006430 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006431 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006432 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006433 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006434
Johan Hedberga664b5b2011-02-19 12:06:02 -03006435 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006436
6437 return err;
6438}
6439
Johan Hedberg744cf192011-11-08 20:40:14 +02006440int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006441 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006442{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006443 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006444 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006445}
6446
Johan Hedberg272d90d2012-02-09 15:26:12 +02006447int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006448 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006449{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006450 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006451 status,
6452 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006453}
Johan Hedberg2a611692011-02-19 12:06:00 -03006454
Brian Gix604086b2011-11-23 08:28:33 -08006455int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006456 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006457{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006458 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006459 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006460}
6461
Johan Hedberg272d90d2012-02-09 15:26:12 +02006462int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006463 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006464{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006465 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006466 status,
6467 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006468}
6469
Johan Hedberg92a25252012-09-06 18:39:26 +03006470int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6471 u8 link_type, u8 addr_type, u32 passkey,
6472 u8 entered)
6473{
6474 struct mgmt_ev_passkey_notify ev;
6475
6476 BT_DBG("%s", hdev->name);
6477
6478 bacpy(&ev.addr.bdaddr, bdaddr);
6479 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6480 ev.passkey = __cpu_to_le32(passkey);
6481 ev.entered = entered;
6482
6483 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6484}
6485
Marcel Holtmanne5460992013-10-15 14:26:23 -07006486void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6487 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006488{
6489 struct mgmt_ev_auth_failed ev;
6490
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006491 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006492 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006493 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006494
Marcel Holtmanne5460992013-10-15 14:26:23 -07006495 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006496}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006497
Marcel Holtmann464996a2013-10-15 14:26:24 -07006498void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006499{
6500 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006501 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006502
6503 if (status) {
6504 u8 mgmt_err = mgmt_status(status);
6505 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006506 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006507 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006508 }
6509
Marcel Holtmann464996a2013-10-15 14:26:24 -07006510 if (test_bit(HCI_AUTH, &hdev->flags))
6511 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6512 &hdev->dev_flags);
6513 else
6514 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6515 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006516
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006517 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006518 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006519
Johan Hedberg47990ea2012-02-22 11:58:37 +02006520 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006521 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006522
6523 if (match.sk)
6524 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006525}
6526
Johan Hedberg890ea892013-03-15 17:06:52 -05006527static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006528{
Johan Hedberg890ea892013-03-15 17:06:52 -05006529 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006530 struct hci_cp_write_eir cp;
6531
Johan Hedberg976eb202012-10-24 21:12:01 +03006532 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006533 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006534
Johan Hedbergc80da272012-02-22 15:38:48 +02006535 memset(hdev->eir, 0, sizeof(hdev->eir));
6536
Johan Hedbergcacaf522012-02-21 00:52:42 +02006537 memset(&cp, 0, sizeof(cp));
6538
Johan Hedberg890ea892013-03-15 17:06:52 -05006539 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006540}
6541
Marcel Holtmann3e248562013-10-15 14:26:25 -07006542void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006543{
6544 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006545 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006546 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006547
6548 if (status) {
6549 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006550
6551 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006552 &hdev->dev_flags)) {
6553 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006554 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006555 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006556
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006557 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6558 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006559 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006560 }
6561
6562 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006563 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006564 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006565 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6566 if (!changed)
6567 changed = test_and_clear_bit(HCI_HS_ENABLED,
6568 &hdev->dev_flags);
6569 else
6570 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006571 }
6572
6573 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6574
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006575 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006576 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006577
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006578 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006579 sock_put(match.sk);
6580
Johan Hedberg890ea892013-03-15 17:06:52 -05006581 hci_req_init(&req, hdev);
6582
Johan Hedberg37699722014-06-24 14:00:27 +03006583 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6584 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6585 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6586 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006587 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006588 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006589 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006590 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006591
6592 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006593}
6594
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006595void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6596{
6597 struct cmd_lookup match = { NULL, hdev };
6598 bool changed = false;
6599
6600 if (status) {
6601 u8 mgmt_err = mgmt_status(status);
6602
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006603 if (enable) {
6604 if (test_and_clear_bit(HCI_SC_ENABLED,
6605 &hdev->dev_flags))
6606 new_settings(hdev, NULL);
6607 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6608 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006609
6610 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6611 cmd_status_rsp, &mgmt_err);
6612 return;
6613 }
6614
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006615 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006616 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006617 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006618 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006619 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6620 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006621
6622 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6623 settings_rsp, &match);
6624
6625 if (changed)
6626 new_settings(hdev, match.sk);
6627
6628 if (match.sk)
6629 sock_put(match.sk);
6630}
6631
Johan Hedberg92da6092013-03-15 17:06:55 -05006632static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006633{
6634 struct cmd_lookup *match = data;
6635
Johan Hedberg90e70452012-02-23 23:09:40 +02006636 if (match->sk == NULL) {
6637 match->sk = cmd->sk;
6638 sock_hold(match->sk);
6639 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006640}
6641
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006642void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6643 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006644{
Johan Hedberg90e70452012-02-23 23:09:40 +02006645 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006646
Johan Hedberg92da6092013-03-15 17:06:55 -05006647 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6648 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6649 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006650
6651 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006652 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6653 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006654
6655 if (match.sk)
6656 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006657}
6658
Marcel Holtmann7667da32013-10-15 14:26:27 -07006659void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006660{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006661 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006662 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006663
Johan Hedberg13928972013-03-15 17:07:00 -05006664 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006665 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006666
6667 memset(&ev, 0, sizeof(ev));
6668 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006669 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006670
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006671 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006672 if (!cmd) {
6673 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006674
Johan Hedberg13928972013-03-15 17:07:00 -05006675 /* If this is a HCI command related to powering on the
6676 * HCI dev don't send any mgmt signals.
6677 */
6678 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006679 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006680 }
6681
Marcel Holtmann7667da32013-10-15 14:26:27 -07006682 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6683 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006684}
Szymon Jancc35938b2011-03-22 13:12:21 +01006685
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006686void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6687 u8 *randomizer192, u8 *hash256,
6688 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006689{
6690 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006691
Johan Hedberg744cf192011-11-08 20:40:14 +02006692 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006693
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006694 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006695 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006696 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006697
6698 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006699 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6700 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006701 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006702 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6703 hash256 && randomizer256) {
6704 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006705
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006706 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6707 memcpy(rp.randomizer192, randomizer192,
6708 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006709
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006710 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6711 memcpy(rp.randomizer256, randomizer256,
6712 sizeof(rp.randomizer256));
6713
6714 cmd_complete(cmd->sk, hdev->id,
6715 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6716 &rp, sizeof(rp));
6717 } else {
6718 struct mgmt_rp_read_local_oob_data rp;
6719
6720 memcpy(rp.hash, hash192, sizeof(rp.hash));
6721 memcpy(rp.randomizer, randomizer192,
6722 sizeof(rp.randomizer));
6723
6724 cmd_complete(cmd->sk, hdev->id,
6725 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6726 &rp, sizeof(rp));
6727 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006728 }
6729
6730 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006731}
Johan Hedberge17acd42011-03-30 23:57:16 +03006732
Marcel Holtmann901801b2013-10-06 23:55:51 -07006733void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006734 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6735 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006736{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006737 char buf[512];
6738 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006739 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006740
Johan Hedberg75ce2082014-07-02 22:42:01 +03006741 /* Don't send events for a non-kernel initiated discovery. With
6742 * LE one exception is if we have pend_le_reports > 0 in which
6743 * case we're doing passive scanning and want these events.
6744 */
6745 if (!hci_discovery_active(hdev)) {
6746 if (link_type == ACL_LINK)
6747 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006748 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006749 return;
6750 }
Andre Guedes12602d02013-04-30 15:29:40 -03006751
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006752 /* Make sure that the buffer is big enough. The 5 extra bytes
6753 * are for the potential CoD field.
6754 */
6755 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006756 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006757
Johan Hedberg1dc06092012-01-15 21:01:23 +02006758 memset(buf, 0, sizeof(buf));
6759
Johan Hedberg841c5642014-07-07 12:45:54 +03006760 bacpy(&ev->addr.bdaddr, bdaddr);
6761 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006762 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006763 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006764
Johan Hedberg1dc06092012-01-15 21:01:23 +02006765 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006766 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006767
Johan Hedberg1dc06092012-01-15 21:01:23 +02006768 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6769 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006770 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006771
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006772 if (scan_rsp_len > 0)
6773 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6774
6775 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6776 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006777
Marcel Holtmann901801b2013-10-06 23:55:51 -07006778 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006779}
Johan Hedberga88a9652011-03-30 13:18:12 +03006780
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006781void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6782 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006783{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006784 struct mgmt_ev_device_found *ev;
6785 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6786 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006787
Johan Hedbergb644ba32012-01-17 21:48:47 +02006788 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006789
Johan Hedbergb644ba32012-01-17 21:48:47 +02006790 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006791
Johan Hedbergb644ba32012-01-17 21:48:47 +02006792 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006793 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006794 ev->rssi = rssi;
6795
6796 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006797 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006798
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006799 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006800
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006801 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006802}
Johan Hedberg314b2382011-04-27 10:29:57 -04006803
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006804void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006805{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006806 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006807 struct pending_cmd *cmd;
6808
Andre Guedes343fb142011-11-22 17:14:19 -03006809 BT_DBG("%s discovering %u", hdev->name, discovering);
6810
Johan Hedberg164a6e72011-11-01 17:06:44 +02006811 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006812 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006813 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006814 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006815
6816 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006817 u8 type = hdev->discovery.type;
6818
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006819 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6820 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006821 mgmt_pending_remove(cmd);
6822 }
6823
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006824 memset(&ev, 0, sizeof(ev));
6825 ev.type = hdev->discovery.type;
6826 ev.discovering = discovering;
6827
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006828 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006829}
Antti Julku5e762442011-08-25 16:48:02 +03006830
Marcel Holtmann5976e602013-10-06 04:08:14 -07006831static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6832{
6833 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006834}
6835
6836void mgmt_reenable_advertising(struct hci_dev *hdev)
6837{
6838 struct hci_request req;
6839
Marcel Holtmann5976e602013-10-06 04:08:14 -07006840 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6841 return;
6842
6843 hci_req_init(&req, hdev);
6844 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006845 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006846}