blob: 68c0698124fb30fb62b32b0cd5bae109957cccf8 [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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Hedberg03811012010-12-08 00:21:06 +0200558
Andre Guedesed3fa312012-07-24 15:03:46 -0300559 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300560 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500561 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
562 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300563 settings |= MGMT_SETTING_DISCOVERABLE;
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 Holtmann5afeac12014-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergaee9b212012-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 Hedberg21a60d32014-06-10 14:05:58 +03001254static void hci_stop_discovery(struct hci_request *req)
1255{
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
1269 break;
1270
1271 case DISCOVERY_RESOLVING:
1272 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1273 NAME_PENDING);
1274 if (!e)
1275 return;
1276
1277 bacpy(&cp.bdaddr, &e->data.bdaddr);
1278 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1279 &cp);
1280
1281 break;
1282
1283 default:
1284 /* Passive scanning */
1285 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1286 hci_req_add_le_scan_disable(req);
1287 break;
1288 }
1289}
1290
Johan Hedberg8b064a32014-02-24 14:52:22 +02001291static int clean_up_hci_state(struct hci_dev *hdev)
1292{
1293 struct hci_request req;
1294 struct hci_conn *conn;
1295
1296 hci_req_init(&req, hdev);
1297
1298 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1299 test_bit(HCI_PSCAN, &hdev->flags)) {
1300 u8 scan = 0x00;
1301 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1302 }
1303
1304 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1305 disable_advertising(&req);
1306
Johan Hedbergf8680f12014-06-10 14:05:59 +03001307 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001308
1309 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1310 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001311 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
Johan Hedbergc9910d02014-02-27 14:35:12 +02001313 switch (conn->state) {
1314 case BT_CONNECTED:
1315 case BT_CONFIG:
1316 dc.handle = cpu_to_le16(conn->handle);
1317 dc.reason = 0x15; /* Terminated due to Power Off */
1318 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1319 break;
1320 case BT_CONNECT:
1321 if (conn->type == LE_LINK)
1322 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1323 0, NULL);
1324 else if (conn->type == ACL_LINK)
1325 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1326 6, &conn->dst);
1327 break;
1328 case BT_CONNECT2:
1329 bacpy(&rej.bdaddr, &conn->dst);
1330 rej.reason = 0x15; /* Terminated due to Power Off */
1331 if (conn->type == ACL_LINK)
1332 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1333 sizeof(rej), &rej);
1334 else if (conn->type == SCO_LINK)
1335 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1336 sizeof(rej), &rej);
1337 break;
1338 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001339 }
1340
1341 return hci_req_run(&req, clean_up_hci_complete);
1342}
1343
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001344static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001345 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001346{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001347 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001348 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001349 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001350
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001351 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001352
Johan Hedberga7e80f22013-01-09 16:05:19 +02001353 if (cp->val != 0x00 && cp->val != 0x01)
1354 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1355 MGMT_STATUS_INVALID_PARAMS);
1356
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001357 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001358
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001359 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1360 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1361 MGMT_STATUS_BUSY);
1362 goto failed;
1363 }
1364
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001365 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1366 cancel_delayed_work(&hdev->power_off);
1367
1368 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001369 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1370 data, len);
1371 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001372 goto failed;
1373 }
1374 }
1375
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001376 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001377 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001378 goto failed;
1379 }
1380
Johan Hedberg03811012010-12-08 00:21:06 +02001381 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1382 if (!cmd) {
1383 err = -ENOMEM;
1384 goto failed;
1385 }
1386
Johan Hedberg8b064a32014-02-24 14:52:22 +02001387 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001388 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001389 err = 0;
1390 } else {
1391 /* Disconnect connections, stop scans, etc */
1392 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001393 if (!err)
1394 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1395 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001396
Johan Hedberg8b064a32014-02-24 14:52:22 +02001397 /* ENODATA means there were no HCI commands queued */
1398 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001399 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001400 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1401 err = 0;
1402 }
1403 }
Johan Hedberg03811012010-12-08 00:21:06 +02001404
1405failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001406 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001407 return err;
1408}
1409
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001410static int new_settings(struct hci_dev *hdev, struct sock *skip)
1411{
1412 __le32 ev;
1413
1414 ev = cpu_to_le32(get_current_settings(hdev));
1415
1416 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1417}
1418
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001419struct cmd_lookup {
1420 struct sock *sk;
1421 struct hci_dev *hdev;
1422 u8 mgmt_status;
1423};
1424
1425static void settings_rsp(struct pending_cmd *cmd, void *data)
1426{
1427 struct cmd_lookup *match = data;
1428
1429 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1430
1431 list_del(&cmd->list);
1432
1433 if (match->sk == NULL) {
1434 match->sk = cmd->sk;
1435 sock_hold(match->sk);
1436 }
1437
1438 mgmt_pending_free(cmd);
1439}
1440
1441static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1442{
1443 u8 *status = data;
1444
1445 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1446 mgmt_pending_remove(cmd);
1447}
1448
Johan Hedberge6fe7982013-10-02 15:45:22 +03001449static u8 mgmt_bredr_support(struct hci_dev *hdev)
1450{
1451 if (!lmp_bredr_capable(hdev))
1452 return MGMT_STATUS_NOT_SUPPORTED;
1453 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1454 return MGMT_STATUS_REJECTED;
1455 else
1456 return MGMT_STATUS_SUCCESS;
1457}
1458
1459static u8 mgmt_le_support(struct hci_dev *hdev)
1460{
1461 if (!lmp_le_capable(hdev))
1462 return MGMT_STATUS_NOT_SUPPORTED;
1463 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1464 return MGMT_STATUS_REJECTED;
1465 else
1466 return MGMT_STATUS_SUCCESS;
1467}
1468
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001469static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1470{
1471 struct pending_cmd *cmd;
1472 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001473 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001474 bool changed;
1475
1476 BT_DBG("status 0x%02x", status);
1477
1478 hci_dev_lock(hdev);
1479
1480 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1481 if (!cmd)
1482 goto unlock;
1483
1484 if (status) {
1485 u8 mgmt_err = mgmt_status(status);
1486 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001487 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001488 goto remove_cmd;
1489 }
1490
1491 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001492 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001493 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1494 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001495
1496 if (hdev->discov_timeout > 0) {
1497 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1498 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1499 to);
1500 }
1501 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001502 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1503 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001504 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001505
1506 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1507
1508 if (changed)
1509 new_settings(hdev, cmd->sk);
1510
Marcel Holtmann970ba522013-10-15 06:33:57 -07001511 /* When the discoverable mode gets changed, make sure
1512 * that class of device has the limited discoverable
1513 * bit correctly set.
1514 */
1515 hci_req_init(&req, hdev);
1516 update_class(&req);
1517 hci_req_run(&req, NULL);
1518
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001519remove_cmd:
1520 mgmt_pending_remove(cmd);
1521
1522unlock:
1523 hci_dev_unlock(hdev);
1524}
1525
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001526static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001527 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001528{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001529 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001530 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001531 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001532 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001533 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001534 int err;
1535
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001536 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001537
Johan Hedberg9a43e252013-10-20 19:00:07 +03001538 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1539 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001540 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001541 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001542
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001543 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001544 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1545 MGMT_STATUS_INVALID_PARAMS);
1546
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001547 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001548
1549 /* Disabling discoverable requires that no timeout is set,
1550 * and enabling limited discoverable requires a timeout.
1551 */
1552 if ((cp->val == 0x00 && timeout > 0) ||
1553 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001554 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001555 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001556
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001557 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001558
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001559 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001560 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001561 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001562 goto failed;
1563 }
1564
1565 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001566 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001567 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001568 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001569 goto failed;
1570 }
1571
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001572 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001573 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001574 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001575 goto failed;
1576 }
1577
1578 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001579 bool changed = false;
1580
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001581 /* Setting limited discoverable when powered off is
1582 * not a valid operation since it requires a timeout
1583 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1584 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001585 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1586 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1587 changed = true;
1588 }
1589
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001590 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001591 if (err < 0)
1592 goto failed;
1593
1594 if (changed)
1595 err = new_settings(hdev, sk);
1596
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001597 goto failed;
1598 }
1599
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001600 /* If the current mode is the same, then just update the timeout
1601 * value with the new value. And if only the timeout gets updated,
1602 * then no need for any HCI transactions.
1603 */
1604 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1605 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1606 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001607 cancel_delayed_work(&hdev->discov_off);
1608 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001609
Marcel Holtmann36261542013-10-15 08:28:51 -07001610 if (cp->val && hdev->discov_timeout > 0) {
1611 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001612 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001613 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001614 }
1615
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001616 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001617 goto failed;
1618 }
1619
1620 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1621 if (!cmd) {
1622 err = -ENOMEM;
1623 goto failed;
1624 }
1625
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001626 /* Cancel any potential discoverable timeout that might be
1627 * still active and store new timeout value. The arming of
1628 * the timeout happens in the complete handler.
1629 */
1630 cancel_delayed_work(&hdev->discov_off);
1631 hdev->discov_timeout = timeout;
1632
Johan Hedbergb456f872013-10-19 23:38:22 +03001633 /* Limited discoverable mode */
1634 if (cp->val == 0x02)
1635 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1636 else
1637 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1638
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001639 hci_req_init(&req, hdev);
1640
Johan Hedberg9a43e252013-10-20 19:00:07 +03001641 /* The procedure for LE-only controllers is much simpler - just
1642 * update the advertising data.
1643 */
1644 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1645 goto update_ad;
1646
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001647 scan = SCAN_PAGE;
1648
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001649 if (cp->val) {
1650 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001651
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001652 if (cp->val == 0x02) {
1653 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001654 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001655 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1656 hci_cp.iac_lap[1] = 0x8b;
1657 hci_cp.iac_lap[2] = 0x9e;
1658 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1659 hci_cp.iac_lap[4] = 0x8b;
1660 hci_cp.iac_lap[5] = 0x9e;
1661 } else {
1662 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001663 hci_cp.num_iac = 1;
1664 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1665 hci_cp.iac_lap[1] = 0x8b;
1666 hci_cp.iac_lap[2] = 0x9e;
1667 }
1668
1669 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1670 (hci_cp.num_iac * 3) + 1, &hci_cp);
1671
1672 scan |= SCAN_INQUIRY;
1673 } else {
1674 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1675 }
1676
1677 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001678
Johan Hedberg9a43e252013-10-20 19:00:07 +03001679update_ad:
1680 update_adv_data(&req);
1681
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001682 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001683 if (err < 0)
1684 mgmt_pending_remove(cmd);
1685
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001686failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001687 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001688 return err;
1689}
1690
Johan Hedberg406d7802013-03-15 17:07:09 -05001691static void write_fast_connectable(struct hci_request *req, bool enable)
1692{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001693 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001694 struct hci_cp_write_page_scan_activity acp;
1695 u8 type;
1696
Johan Hedberg547003b2013-10-21 16:51:53 +03001697 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1698 return;
1699
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001700 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1701 return;
1702
Johan Hedberg406d7802013-03-15 17:07:09 -05001703 if (enable) {
1704 type = PAGE_SCAN_TYPE_INTERLACED;
1705
1706 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001707 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001708 } else {
1709 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1710
1711 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001712 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001713 }
1714
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001715 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001716
Johan Hedbergbd98b992013-03-15 17:07:13 -05001717 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1718 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1719 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1720 sizeof(acp), &acp);
1721
1722 if (hdev->page_scan_type != type)
1723 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001724}
1725
Johan Hedberg2b76f452013-03-15 17:07:04 -05001726static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1727{
1728 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001729 struct mgmt_mode *cp;
1730 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001731
1732 BT_DBG("status 0x%02x", status);
1733
1734 hci_dev_lock(hdev);
1735
1736 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1737 if (!cmd)
1738 goto unlock;
1739
Johan Hedberg37438c12013-10-14 16:20:05 +03001740 if (status) {
1741 u8 mgmt_err = mgmt_status(status);
1742 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1743 goto remove_cmd;
1744 }
1745
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001746 cp = cmd->param;
1747 if (cp->val)
1748 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1749 else
1750 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1751
Johan Hedberg2b76f452013-03-15 17:07:04 -05001752 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1753
Johan Hedberg2b7be332014-07-07 14:40:22 +03001754 if (changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001755 new_settings(hdev, cmd->sk);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001756 hci_update_background_scan(hdev);
1757 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001758
Johan Hedberg37438c12013-10-14 16:20:05 +03001759remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001760 mgmt_pending_remove(cmd);
1761
1762unlock:
1763 hci_dev_unlock(hdev);
1764}
1765
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001766static int set_connectable_update_settings(struct hci_dev *hdev,
1767 struct sock *sk, u8 val)
1768{
1769 bool changed = false;
1770 int err;
1771
1772 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1773 changed = true;
1774
1775 if (val) {
1776 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1777 } else {
1778 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1779 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1780 }
1781
1782 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1783 if (err < 0)
1784 return err;
1785
1786 if (changed)
1787 return new_settings(hdev, sk);
1788
1789 return 0;
1790}
1791
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001792static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001793 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001794{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001795 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001796 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001797 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001798 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001799 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001800
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001801 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001802
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001803 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1804 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001805 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001806 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001807
Johan Hedberga7e80f22013-01-09 16:05:19 +02001808 if (cp->val != 0x00 && cp->val != 0x01)
1809 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1810 MGMT_STATUS_INVALID_PARAMS);
1811
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001812 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001813
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001814 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001815 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001816 goto failed;
1817 }
1818
1819 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001820 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001821 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001822 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001823 goto failed;
1824 }
1825
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001826 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1827 if (!cmd) {
1828 err = -ENOMEM;
1829 goto failed;
1830 }
1831
Johan Hedberg2b76f452013-03-15 17:07:04 -05001832 hci_req_init(&req, hdev);
1833
Johan Hedberg9a43e252013-10-20 19:00:07 +03001834 /* If BR/EDR is not enabled and we disable advertising as a
1835 * by-product of disabling connectable, we need to update the
1836 * advertising flags.
1837 */
1838 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1839 if (!cp->val) {
1840 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1841 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1842 }
1843 update_adv_data(&req);
1844 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001845 if (cp->val) {
1846 scan = SCAN_PAGE;
1847 } else {
1848 scan = 0;
1849
1850 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001851 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001852 cancel_delayed_work(&hdev->discov_off);
1853 }
1854
1855 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1856 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001857
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001858 /* If we're going from non-connectable to connectable or
1859 * vice-versa when fast connectable is enabled ensure that fast
1860 * connectable gets disabled. write_fast_connectable won't do
1861 * anything if the page scan parameters are already what they
1862 * should be.
1863 */
1864 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001865 write_fast_connectable(&req, false);
1866
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001867 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001868 !test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001870
Johan Hedberg2b76f452013-03-15 17:07:04 -05001871 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001872 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001873 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001874 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001875 err = set_connectable_update_settings(hdev, sk,
1876 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001877 goto failed;
1878 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
1880failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001881 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 return err;
1883}
1884
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001885static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001886 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001887{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001888 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001889 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001890 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001891
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001892 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001893
Johan Hedberga7e80f22013-01-09 16:05:19 +02001894 if (cp->val != 0x00 && cp->val != 0x01)
1895 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1896 MGMT_STATUS_INVALID_PARAMS);
1897
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001898 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001899
1900 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001901 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001902 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001903 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001904
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001905 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001906 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001907 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001908
Marcel Holtmann55594352013-10-06 16:11:57 -07001909 if (changed)
1910 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001911
Marcel Holtmann55594352013-10-06 16:11:57 -07001912unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001913 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001914 return err;
1915}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001916
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001917static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1918 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001919{
1920 struct mgmt_mode *cp = data;
1921 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001922 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001923 int err;
1924
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001925 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001926
Johan Hedberge6fe7982013-10-02 15:45:22 +03001927 status = mgmt_bredr_support(hdev);
1928 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001929 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001930 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001931
Johan Hedberga7e80f22013-01-09 16:05:19 +02001932 if (cp->val != 0x00 && cp->val != 0x01)
1933 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1934 MGMT_STATUS_INVALID_PARAMS);
1935
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001936 hci_dev_lock(hdev);
1937
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001938 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001939 bool changed = false;
1940
1941 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001942 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001943 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1944 changed = true;
1945 }
1946
1947 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1948 if (err < 0)
1949 goto failed;
1950
1951 if (changed)
1952 err = new_settings(hdev, sk);
1953
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001954 goto failed;
1955 }
1956
1957 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001958 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001959 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001960 goto failed;
1961 }
1962
1963 val = !!cp->val;
1964
1965 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1966 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1967 goto failed;
1968 }
1969
1970 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1971 if (!cmd) {
1972 err = -ENOMEM;
1973 goto failed;
1974 }
1975
1976 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1977 if (err < 0) {
1978 mgmt_pending_remove(cmd);
1979 goto failed;
1980 }
1981
1982failed:
1983 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001984 return err;
1985}
1986
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001987static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001988{
1989 struct mgmt_mode *cp = data;
1990 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001991 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001992 int err;
1993
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001994 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001995
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001996 status = mgmt_bredr_support(hdev);
1997 if (status)
1998 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1999
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002000 if (!lmp_ssp_capable(hdev))
2001 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2002 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002003
Johan Hedberga7e80f22013-01-09 16:05:19 +02002004 if (cp->val != 0x00 && cp->val != 0x01)
2005 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2006 MGMT_STATUS_INVALID_PARAMS);
2007
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002008 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002009
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002010 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002011 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002012
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002013 if (cp->val) {
2014 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2015 &hdev->dev_flags);
2016 } else {
2017 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2018 &hdev->dev_flags);
2019 if (!changed)
2020 changed = test_and_clear_bit(HCI_HS_ENABLED,
2021 &hdev->dev_flags);
2022 else
2023 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002024 }
2025
2026 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2027 if (err < 0)
2028 goto failed;
2029
2030 if (changed)
2031 err = new_settings(hdev, sk);
2032
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002033 goto failed;
2034 }
2035
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002036 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2037 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002038 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2039 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002040 goto failed;
2041 }
2042
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002043 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002044 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
Johan Hedberg37699722014-06-24 14:00:27 +03002054 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2055 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2056 sizeof(cp->val), &cp->val);
2057
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002058 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002059 if (err < 0) {
2060 mgmt_pending_remove(cmd);
2061 goto failed;
2062 }
2063
2064failed:
2065 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066 return err;
2067}
2068
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002069static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002070{
2071 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002072 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002073 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002074 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002075
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002076 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002077
Johan Hedberge6fe7982013-10-02 15:45:22 +03002078 status = mgmt_bredr_support(hdev);
2079 if (status)
2080 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002081
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002082 if (!lmp_ssp_capable(hdev))
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2084 MGMT_STATUS_NOT_SUPPORTED);
2085
2086 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2087 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2088 MGMT_STATUS_REJECTED);
2089
Johan Hedberga7e80f22013-01-09 16:05:19 +02002090 if (cp->val != 0x00 && cp->val != 0x01)
2091 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2092 MGMT_STATUS_INVALID_PARAMS);
2093
Marcel Holtmannee392692013-10-01 22:59:23 -07002094 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002095
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002096 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002097 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002098 } else {
2099 if (hdev_is_powered(hdev)) {
2100 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2101 MGMT_STATUS_REJECTED);
2102 goto unlock;
2103 }
2104
Marcel Holtmannee392692013-10-01 22:59:23 -07002105 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002106 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002107
2108 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2109 if (err < 0)
2110 goto unlock;
2111
2112 if (changed)
2113 err = new_settings(hdev, sk);
2114
2115unlock:
2116 hci_dev_unlock(hdev);
2117 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002118}
2119
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002120static void le_enable_complete(struct hci_dev *hdev, u8 status)
2121{
2122 struct cmd_lookup match = { NULL, hdev };
2123
2124 if (status) {
2125 u8 mgmt_err = mgmt_status(status);
2126
2127 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2128 &mgmt_err);
2129 return;
2130 }
2131
2132 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2133
2134 new_settings(hdev, match.sk);
2135
2136 if (match.sk)
2137 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002138
2139 /* Make sure the controller has a good default for
2140 * advertising data. Restrict the update to when LE
2141 * has actually been enabled. During power on, the
2142 * update in powered_update_hci will take care of it.
2143 */
2144 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2145 struct hci_request req;
2146
2147 hci_dev_lock(hdev);
2148
2149 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002150 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002151 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002152 hci_req_run(&req, NULL);
2153
Johan Hedberga70f4b52014-07-07 15:19:50 +03002154 hci_update_background_scan(hdev);
2155
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002156 hci_dev_unlock(hdev);
2157 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002158}
2159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002160static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002161{
2162 struct mgmt_mode *cp = data;
2163 struct hci_cp_write_le_host_supported hci_cp;
2164 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002165 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002166 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002167 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002168
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002169 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002170
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002171 if (!lmp_le_capable(hdev))
2172 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2173 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002174
Johan Hedberga7e80f22013-01-09 16:05:19 +02002175 if (cp->val != 0x00 && cp->val != 0x01)
2176 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2177 MGMT_STATUS_INVALID_PARAMS);
2178
Johan Hedbergc73eee92013-04-19 18:35:21 +03002179 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002180 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002181 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2182 MGMT_STATUS_REJECTED);
2183
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002184 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002185
2186 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002187 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002188
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002189 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002190 bool changed = false;
2191
2192 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2193 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2194 changed = true;
2195 }
2196
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002197 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2198 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002199 changed = true;
2200 }
2201
Johan Hedberg06199cf2012-02-22 16:37:11 +02002202 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2203 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002204 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002205
2206 if (changed)
2207 err = new_settings(hdev, sk);
2208
Johan Hedberg1de028c2012-02-29 19:55:35 -08002209 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002210 }
2211
Johan Hedberg4375f102013-09-25 13:26:10 +03002212 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2213 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002214 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002215 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002216 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002217 }
2218
2219 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2220 if (!cmd) {
2221 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002222 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002223 }
2224
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002225 hci_req_init(&req, hdev);
2226
Johan Hedberg06199cf2012-02-22 16:37:11 +02002227 memset(&hci_cp, 0, sizeof(hci_cp));
2228
2229 if (val) {
2230 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002231 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002232 } else {
2233 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2234 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002235 }
2236
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002237 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2238 &hci_cp);
2239
2240 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302241 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002242 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002243
Johan Hedberg1de028c2012-02-29 19:55:35 -08002244unlock:
2245 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246 return err;
2247}
2248
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002249/* This is a helper function to test for pending mgmt commands that can
2250 * cause CoD or EIR HCI commands. We can only allow one such pending
2251 * mgmt command at a time since otherwise we cannot easily track what
2252 * the current values are, will be, and based on that calculate if a new
2253 * HCI command needs to be sent and if yes with what value.
2254 */
2255static bool pending_eir_or_class(struct hci_dev *hdev)
2256{
2257 struct pending_cmd *cmd;
2258
2259 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2260 switch (cmd->opcode) {
2261 case MGMT_OP_ADD_UUID:
2262 case MGMT_OP_REMOVE_UUID:
2263 case MGMT_OP_SET_DEV_CLASS:
2264 case MGMT_OP_SET_POWERED:
2265 return true;
2266 }
2267 }
2268
2269 return false;
2270}
2271
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002272static const u8 bluetooth_base_uuid[] = {
2273 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2274 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2275};
2276
2277static u8 get_uuid_size(const u8 *uuid)
2278{
2279 u32 val;
2280
2281 if (memcmp(uuid, bluetooth_base_uuid, 12))
2282 return 128;
2283
2284 val = get_unaligned_le32(&uuid[12]);
2285 if (val > 0xffff)
2286 return 32;
2287
2288 return 16;
2289}
2290
Johan Hedberg92da6092013-03-15 17:06:55 -05002291static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2292{
2293 struct pending_cmd *cmd;
2294
2295 hci_dev_lock(hdev);
2296
2297 cmd = mgmt_pending_find(mgmt_op, hdev);
2298 if (!cmd)
2299 goto unlock;
2300
2301 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2302 hdev->dev_class, 3);
2303
2304 mgmt_pending_remove(cmd);
2305
2306unlock:
2307 hci_dev_unlock(hdev);
2308}
2309
2310static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2311{
2312 BT_DBG("status 0x%02x", status);
2313
2314 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2315}
2316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002317static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002318{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002319 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002320 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002321 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002322 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002323 int err;
2324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002325 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002326
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002327 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002328
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002329 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002330 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002331 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002332 goto failed;
2333 }
2334
Andre Guedes92c4c202012-06-07 19:05:44 -03002335 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002336 if (!uuid) {
2337 err = -ENOMEM;
2338 goto failed;
2339 }
2340
2341 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002342 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002343 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002344
Johan Hedbergde66aa62013-01-27 00:31:27 +02002345 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002346
Johan Hedberg890ea892013-03-15 17:06:52 -05002347 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002348
Johan Hedberg890ea892013-03-15 17:06:52 -05002349 update_class(&req);
2350 update_eir(&req);
2351
Johan Hedberg92da6092013-03-15 17:06:55 -05002352 err = hci_req_run(&req, add_uuid_complete);
2353 if (err < 0) {
2354 if (err != -ENODATA)
2355 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002356
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002357 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002358 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002359 goto failed;
2360 }
2361
2362 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002363 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002364 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002365 goto failed;
2366 }
2367
2368 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002369
2370failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002371 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002372 return err;
2373}
2374
Johan Hedberg24b78d02012-02-23 23:24:30 +02002375static bool enable_service_cache(struct hci_dev *hdev)
2376{
2377 if (!hdev_is_powered(hdev))
2378 return false;
2379
2380 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002381 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2382 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002383 return true;
2384 }
2385
2386 return false;
2387}
2388
Johan Hedberg92da6092013-03-15 17:06:55 -05002389static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2390{
2391 BT_DBG("status 0x%02x", status);
2392
2393 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2394}
2395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002397 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002398{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002399 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002400 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002401 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002402 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 -05002403 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404 int err, found;
2405
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002406 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002407
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002408 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002409
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002410 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002411 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002412 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002413 goto unlock;
2414 }
2415
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002416 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002417 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002418
Johan Hedberg24b78d02012-02-23 23:24:30 +02002419 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002420 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002421 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002422 goto unlock;
2423 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002424
Johan Hedberg9246a862012-02-23 21:33:16 +02002425 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002426 }
2427
2428 found = 0;
2429
Johan Hedberg056341c2013-01-27 00:31:30 +02002430 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002431 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2432 continue;
2433
2434 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002435 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002436 found++;
2437 }
2438
2439 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002440 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002441 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002442 goto unlock;
2443 }
2444
Johan Hedberg9246a862012-02-23 21:33:16 +02002445update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002446 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002447
Johan Hedberg890ea892013-03-15 17:06:52 -05002448 update_class(&req);
2449 update_eir(&req);
2450
Johan Hedberg92da6092013-03-15 17:06:55 -05002451 err = hci_req_run(&req, remove_uuid_complete);
2452 if (err < 0) {
2453 if (err != -ENODATA)
2454 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002455
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002456 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002457 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002458 goto unlock;
2459 }
2460
2461 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002462 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002463 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002464 goto unlock;
2465 }
2466
2467 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002468
2469unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002470 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002471 return err;
2472}
2473
Johan Hedberg92da6092013-03-15 17:06:55 -05002474static void set_class_complete(struct hci_dev *hdev, u8 status)
2475{
2476 BT_DBG("status 0x%02x", status);
2477
2478 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2479}
2480
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002481static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002482 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002483{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002484 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002485 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002486 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002487 int err;
2488
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002490
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002491 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002492 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2493 MGMT_STATUS_NOT_SUPPORTED);
2494
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002495 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002496
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002497 if (pending_eir_or_class(hdev)) {
2498 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2499 MGMT_STATUS_BUSY);
2500 goto unlock;
2501 }
2502
2503 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2504 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2505 MGMT_STATUS_INVALID_PARAMS);
2506 goto unlock;
2507 }
2508
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002509 hdev->major_class = cp->major;
2510 hdev->minor_class = cp->minor;
2511
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002512 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002513 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002514 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002515 goto unlock;
2516 }
2517
Johan Hedberg890ea892013-03-15 17:06:52 -05002518 hci_req_init(&req, hdev);
2519
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002520 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002521 hci_dev_unlock(hdev);
2522 cancel_delayed_work_sync(&hdev->service_cache);
2523 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002525 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002526
Johan Hedberg890ea892013-03-15 17:06:52 -05002527 update_class(&req);
2528
Johan Hedberg92da6092013-03-15 17:06:55 -05002529 err = hci_req_run(&req, set_class_complete);
2530 if (err < 0) {
2531 if (err != -ENODATA)
2532 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 goto unlock;
2537 }
2538
2539 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002541 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 goto unlock;
2543 }
2544
2545 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002546
Johan Hedbergb5235a62012-02-21 14:32:24 +02002547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002549 return err;
2550}
2551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002552static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002553 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002554{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002555 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002556 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2557 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002558 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002559 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002560 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002561
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002562 BT_DBG("request for %s", hdev->name);
2563
2564 if (!lmp_bredr_capable(hdev))
2565 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2566 MGMT_STATUS_NOT_SUPPORTED);
2567
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002568 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002569 if (key_count > max_key_count) {
2570 BT_ERR("load_link_keys: too big key_count value %u",
2571 key_count);
2572 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2573 MGMT_STATUS_INVALID_PARAMS);
2574 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002575
Johan Hedberg86742e12011-11-07 23:13:38 +02002576 expected_len = sizeof(*cp) + key_count *
2577 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002578 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002579 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002580 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002581 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002582 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002583 }
2584
Johan Hedberg4ae14302013-01-20 14:27:13 +02002585 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2586 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2587 MGMT_STATUS_INVALID_PARAMS);
2588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002589 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002590 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002591
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002592 for (i = 0; i < key_count; i++) {
2593 struct mgmt_link_key_info *key = &cp->keys[i];
2594
Marcel Holtmann8e991132014-01-10 02:07:25 -08002595 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002596 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2597 MGMT_STATUS_INVALID_PARAMS);
2598 }
2599
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002600 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002601
2602 hci_link_keys_clear(hdev);
2603
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002604 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002605 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2606 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002607 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002608 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2609 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002610
2611 if (changed)
2612 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002613
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002614 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002615 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002616
Johan Hedberg58e92932014-06-24 14:00:26 +03002617 /* Always ignore debug keys and require a new pairing if
2618 * the user wants to use them.
2619 */
2620 if (key->type == HCI_LK_DEBUG_COMBINATION)
2621 continue;
2622
Johan Hedberg7652ff62014-06-24 13:15:49 +03002623 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2624 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002625 }
2626
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002627 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002628
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002629 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002630
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002631 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632}
2633
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002634static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002635 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002636{
2637 struct mgmt_ev_device_unpaired ev;
2638
2639 bacpy(&ev.addr.bdaddr, bdaddr);
2640 ev.addr.type = addr_type;
2641
2642 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002643 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002644}
2645
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002646static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002647 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002648{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002649 struct mgmt_cp_unpair_device *cp = data;
2650 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002651 struct hci_cp_disconnect dc;
2652 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002654 int err;
2655
Johan Hedberga8a1d192011-11-10 15:54:38 +02002656 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002657 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2658 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002659
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002660 if (!bdaddr_type_is_valid(cp->addr.type))
2661 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2662 MGMT_STATUS_INVALID_PARAMS,
2663 &rp, sizeof(rp));
2664
Johan Hedberg118da702013-01-20 14:27:20 +02002665 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2666 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2667 MGMT_STATUS_INVALID_PARAMS,
2668 &rp, sizeof(rp));
2669
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002670 hci_dev_lock(hdev);
2671
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002672 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002673 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002674 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002675 goto unlock;
2676 }
2677
Johan Hedberge0b2b272014-02-18 17:14:31 +02002678 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002679 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002680 } else {
2681 u8 addr_type;
2682
2683 if (cp->addr.type == BDADDR_LE_PUBLIC)
2684 addr_type = ADDR_LE_DEV_PUBLIC;
2685 else
2686 addr_type = ADDR_LE_DEV_RANDOM;
2687
Johan Hedberga7ec7332014-02-18 17:14:35 +02002688 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2689
Andre Guedesa9b0a042014-02-26 20:21:52 -03002690 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2691
Johan Hedberge0b2b272014-02-18 17:14:31 +02002692 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2693 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002694
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002695 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002696 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002697 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002698 goto unlock;
2699 }
2700
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002701 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002702 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002703 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002704 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002705 else
2706 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002707 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002708 } else {
2709 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711
Johan Hedberga8a1d192011-11-10 15:54:38 +02002712 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002713 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002714 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002715 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002716 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002717 }
2718
Johan Hedberg124f6e32012-02-09 13:50:12 +02002719 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002720 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002721 if (!cmd) {
2722 err = -ENOMEM;
2723 goto unlock;
2724 }
2725
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002726 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002727 dc.reason = 0x13; /* Remote User Terminated Connection */
2728 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2729 if (err < 0)
2730 mgmt_pending_remove(cmd);
2731
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002733 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002734 return err;
2735}
2736
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002737static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002738 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002739{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002740 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002741 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002742 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002743 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002744 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002745 int err;
2746
2747 BT_DBG("");
2748
Johan Hedberg06a63b12013-01-20 14:27:21 +02002749 memset(&rp, 0, sizeof(rp));
2750 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2751 rp.addr.type = cp->addr.type;
2752
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002753 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002754 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2755 MGMT_STATUS_INVALID_PARAMS,
2756 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002757
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002758 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002759
2760 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002761 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2762 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002763 goto failed;
2764 }
2765
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002766 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002767 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2768 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002769 goto failed;
2770 }
2771
Andre Guedes591f47f2012-04-24 21:02:49 -03002772 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002773 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2774 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002775 else
2776 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002777
Vishal Agarwalf9607272012-06-13 05:32:43 +05302778 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002779 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2780 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002781 goto failed;
2782 }
2783
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002784 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002785 if (!cmd) {
2786 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002787 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002788 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002789
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002790 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002791 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002792
2793 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2794 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002795 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002796
2797failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002798 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002799 return err;
2800}
2801
Andre Guedes57c14772012-04-24 21:02:50 -03002802static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002803{
2804 switch (link_type) {
2805 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002806 switch (addr_type) {
2807 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002808 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002809
Johan Hedberg48264f02011-11-09 13:58:58 +02002810 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002811 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002812 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002813 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002814
Johan Hedberg4c659c32011-11-07 23:13:39 +02002815 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002816 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002817 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002818 }
2819}
2820
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002821static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2822 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002823{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002824 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002825 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002826 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002827 int err;
2828 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002829
2830 BT_DBG("");
2831
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002832 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002833
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002834 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002835 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002836 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002837 goto unlock;
2838 }
2839
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002840 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002841 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2842 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002843 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002844 }
2845
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002846 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002847 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002848 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002849 err = -ENOMEM;
2850 goto unlock;
2851 }
2852
Johan Hedberg2784eb42011-01-21 13:56:35 +02002853 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002854 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002855 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2856 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002857 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002858 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002859 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002860 continue;
2861 i++;
2862 }
2863
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002864 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002865
Johan Hedberg4c659c32011-11-07 23:13:39 +02002866 /* Recalculate length in case of filtered SCO connections, etc */
2867 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002869 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002870 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002871
Johan Hedberga38528f2011-01-22 06:46:43 +02002872 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002873
2874unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002875 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002876 return err;
2877}
2878
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002879static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002880 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002881{
2882 struct pending_cmd *cmd;
2883 int err;
2884
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002885 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002886 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002887 if (!cmd)
2888 return -ENOMEM;
2889
Johan Hedbergd8457692012-02-17 14:24:57 +02002890 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002891 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002892 if (err < 0)
2893 mgmt_pending_remove(cmd);
2894
2895 return err;
2896}
2897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002898static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002899 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002900{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002901 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002902 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002903 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002904 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002905 int err;
2906
2907 BT_DBG("");
2908
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002909 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002910
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002911 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002912 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002913 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002914 goto failed;
2915 }
2916
Johan Hedbergd8457692012-02-17 14:24:57 +02002917 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002918 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002919 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002920 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002921 goto failed;
2922 }
2923
2924 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002925 struct mgmt_cp_pin_code_neg_reply ncp;
2926
2927 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002928
2929 BT_ERR("PIN code is not 16 bytes long");
2930
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002931 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002932 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002933 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002934 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002935
2936 goto failed;
2937 }
2938
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002939 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002940 if (!cmd) {
2941 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002942 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002943 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002944
Johan Hedbergd8457692012-02-17 14:24:57 +02002945 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002946 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002947 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002948
2949 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2950 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002951 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002952
2953failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002954 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002955 return err;
2956}
2957
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002958static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2959 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002960{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002961 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002962
2963 BT_DBG("");
2964
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002965 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2966 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2967 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2968
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002969 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002970
2971 hdev->io_capability = cp->io_capability;
2972
2973 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002974 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002976 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002977
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2979 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002980}
2981
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002982static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002983{
2984 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002985 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002986
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002987 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002988 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2989 continue;
2990
Johan Hedberge9a416b2011-02-19 12:05:56 -03002991 if (cmd->user_data != conn)
2992 continue;
2993
2994 return cmd;
2995 }
2996
2997 return NULL;
2998}
2999
3000static void pairing_complete(struct pending_cmd *cmd, u8 status)
3001{
3002 struct mgmt_rp_pair_device rp;
3003 struct hci_conn *conn = cmd->user_data;
3004
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003005 bacpy(&rp.addr.bdaddr, &conn->dst);
3006 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003007
Johan Hedbergaee9b212012-02-18 15:07:59 +02003008 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003009 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003010
3011 /* So we don't get further callbacks for this connection */
3012 conn->connect_cfm_cb = NULL;
3013 conn->security_cfm_cb = NULL;
3014 conn->disconn_cfm_cb = NULL;
3015
David Herrmann76a68ba2013-04-06 20:28:37 +02003016 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003017
Johan Hedberga664b5b2011-02-19 12:06:02 -03003018 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003019}
3020
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003021void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3022{
3023 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3024 struct pending_cmd *cmd;
3025
3026 cmd = find_pairing(conn);
3027 if (cmd)
3028 pairing_complete(cmd, status);
3029}
3030
Johan Hedberge9a416b2011-02-19 12:05:56 -03003031static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3032{
3033 struct pending_cmd *cmd;
3034
3035 BT_DBG("status %u", status);
3036
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003037 cmd = find_pairing(conn);
3038 if (!cmd)
3039 BT_DBG("Unable to find a pending command");
3040 else
Johan Hedberge2113262012-02-18 15:20:03 +02003041 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003042}
3043
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003044static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303045{
3046 struct pending_cmd *cmd;
3047
3048 BT_DBG("status %u", status);
3049
3050 if (!status)
3051 return;
3052
3053 cmd = find_pairing(conn);
3054 if (!cmd)
3055 BT_DBG("Unable to find a pending command");
3056 else
3057 pairing_complete(cmd, mgmt_status(status));
3058}
3059
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003060static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003061 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003062{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003063 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003064 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003065 struct pending_cmd *cmd;
3066 u8 sec_level, auth_type;
3067 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003068 int err;
3069
3070 BT_DBG("");
3071
Szymon Jancf950a30e2013-01-18 12:48:07 +01003072 memset(&rp, 0, sizeof(rp));
3073 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3074 rp.addr.type = cp->addr.type;
3075
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003076 if (!bdaddr_type_is_valid(cp->addr.type))
3077 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3078 MGMT_STATUS_INVALID_PARAMS,
3079 &rp, sizeof(rp));
3080
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003081 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3082 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3083 MGMT_STATUS_INVALID_PARAMS,
3084 &rp, sizeof(rp));
3085
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003086 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003087
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003088 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003089 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3090 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003091 goto unlock;
3092 }
3093
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003094 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003095 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003096
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003097 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003098 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3099 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003100 } else {
3101 u8 addr_type;
3102
3103 /* Convert from L2CAP channel address type to HCI address type
3104 */
3105 if (cp->addr.type == BDADDR_LE_PUBLIC)
3106 addr_type = ADDR_LE_DEV_PUBLIC;
3107 else
3108 addr_type = ADDR_LE_DEV_RANDOM;
3109
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003110 /* When pairing a new device, it is expected to remember
3111 * this device for future connections. Adding the connection
3112 * parameter information ahead of time allows tracking
3113 * of the slave preferred values and will speed up any
3114 * further connection establishment.
3115 *
3116 * If connection parameters already exist, then they
3117 * will be kept and this function does nothing.
3118 */
3119 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3120
Johan Hedbergcdd62752014-07-07 15:02:28 +03003121 /* Request a connection with master = true role */
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003122 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedbergcdd62752014-07-07 15:02:28 +03003123 sec_level, HCI_LE_CONN_TIMEOUT, true);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003124 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003125
Ville Tervo30e76272011-02-22 16:10:53 -03003126 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003127 int status;
3128
3129 if (PTR_ERR(conn) == -EBUSY)
3130 status = MGMT_STATUS_BUSY;
3131 else
3132 status = MGMT_STATUS_CONNECT_FAILED;
3133
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003134 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003135 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003136 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137 goto unlock;
3138 }
3139
3140 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003141 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003142 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003143 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003144 goto unlock;
3145 }
3146
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003147 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148 if (!cmd) {
3149 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003150 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003151 goto unlock;
3152 }
3153
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003154 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003155 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003156 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003157 conn->security_cfm_cb = pairing_complete_cb;
3158 conn->disconn_cfm_cb = pairing_complete_cb;
3159 } else {
3160 conn->connect_cfm_cb = le_pairing_complete_cb;
3161 conn->security_cfm_cb = le_pairing_complete_cb;
3162 conn->disconn_cfm_cb = le_pairing_complete_cb;
3163 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003164
Johan Hedberge9a416b2011-02-19 12:05:56 -03003165 conn->io_capability = cp->io_cap;
3166 cmd->user_data = conn;
3167
3168 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003169 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003170 pairing_complete(cmd, 0);
3171
3172 err = 0;
3173
3174unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003175 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003176 return err;
3177}
3178
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003179static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3180 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003181{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003182 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003183 struct pending_cmd *cmd;
3184 struct hci_conn *conn;
3185 int err;
3186
3187 BT_DBG("");
3188
Johan Hedberg28424702012-02-02 04:02:29 +02003189 hci_dev_lock(hdev);
3190
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003191 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003192 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003193 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003194 goto unlock;
3195 }
3196
Johan Hedberg28424702012-02-02 04:02:29 +02003197 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3198 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003199 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003200 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003201 goto unlock;
3202 }
3203
3204 conn = cmd->user_data;
3205
3206 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003207 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003208 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003209 goto unlock;
3210 }
3211
3212 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3213
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003214 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003215 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003216unlock:
3217 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003218 return err;
3219}
3220
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003221static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003222 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003223 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003224{
Johan Hedberga5c29682011-02-19 12:05:57 -03003225 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003226 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003227 int err;
3228
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003229 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003230
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003231 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003232 err = cmd_complete(sk, hdev->id, mgmt_op,
3233 MGMT_STATUS_NOT_POWERED, addr,
3234 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003235 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003236 }
3237
Johan Hedberg1707c602013-03-15 17:07:15 -05003238 if (addr->type == BDADDR_BREDR)
3239 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003240 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003241 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003242
Johan Hedberg272d90d2012-02-09 15:26:12 +02003243 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003244 err = cmd_complete(sk, hdev->id, mgmt_op,
3245 MGMT_STATUS_NOT_CONNECTED, addr,
3246 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003247 goto done;
3248 }
3249
Johan Hedberg1707c602013-03-15 17:07:15 -05003250 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003251 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003252 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003253 err = cmd_complete(sk, hdev->id, mgmt_op,
3254 MGMT_STATUS_SUCCESS, addr,
3255 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003256 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003257 err = cmd_complete(sk, hdev->id, mgmt_op,
3258 MGMT_STATUS_FAILED, addr,
3259 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003260
Brian Gix47c15e22011-11-16 13:53:14 -08003261 goto done;
3262 }
3263
Johan Hedberg1707c602013-03-15 17:07:15 -05003264 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003265 if (!cmd) {
3266 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003267 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003268 }
3269
Brian Gix0df4c182011-11-16 13:53:13 -08003270 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003271 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3272 struct hci_cp_user_passkey_reply cp;
3273
Johan Hedberg1707c602013-03-15 17:07:15 -05003274 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003275 cp.passkey = passkey;
3276 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3277 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003278 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3279 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003280
Johan Hedberga664b5b2011-02-19 12:06:02 -03003281 if (err < 0)
3282 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003283
Brian Gix0df4c182011-11-16 13:53:13 -08003284done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003285 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003286 return err;
3287}
3288
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303289static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3290 void *data, u16 len)
3291{
3292 struct mgmt_cp_pin_code_neg_reply *cp = data;
3293
3294 BT_DBG("");
3295
Johan Hedberg1707c602013-03-15 17:07:15 -05003296 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303297 MGMT_OP_PIN_CODE_NEG_REPLY,
3298 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3299}
3300
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003301static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3302 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003303{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003304 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003305
3306 BT_DBG("");
3307
3308 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003309 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003310 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003311
Johan Hedberg1707c602013-03-15 17:07:15 -05003312 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003313 MGMT_OP_USER_CONFIRM_REPLY,
3314 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003315}
3316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003317static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003318 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003319{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003320 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003321
3322 BT_DBG("");
3323
Johan Hedberg1707c602013-03-15 17:07:15 -05003324 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003325 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3326 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003327}
3328
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003329static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3330 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003331{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003332 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003333
3334 BT_DBG("");
3335
Johan Hedberg1707c602013-03-15 17:07:15 -05003336 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003337 MGMT_OP_USER_PASSKEY_REPLY,
3338 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003339}
3340
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003341static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003342 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003343{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003344 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003345
3346 BT_DBG("");
3347
Johan Hedberg1707c602013-03-15 17:07:15 -05003348 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003349 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3350 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003351}
3352
Johan Hedberg13928972013-03-15 17:07:00 -05003353static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003354{
Johan Hedberg13928972013-03-15 17:07:00 -05003355 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003356 struct hci_cp_write_local_name cp;
3357
Johan Hedberg13928972013-03-15 17:07:00 -05003358 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003359
Johan Hedberg890ea892013-03-15 17:06:52 -05003360 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003361}
3362
Johan Hedberg13928972013-03-15 17:07:00 -05003363static void set_name_complete(struct hci_dev *hdev, u8 status)
3364{
3365 struct mgmt_cp_set_local_name *cp;
3366 struct pending_cmd *cmd;
3367
3368 BT_DBG("status 0x%02x", status);
3369
3370 hci_dev_lock(hdev);
3371
3372 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3373 if (!cmd)
3374 goto unlock;
3375
3376 cp = cmd->param;
3377
3378 if (status)
3379 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3380 mgmt_status(status));
3381 else
3382 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3383 cp, sizeof(*cp));
3384
3385 mgmt_pending_remove(cmd);
3386
3387unlock:
3388 hci_dev_unlock(hdev);
3389}
3390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003391static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003392 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003393{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003394 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003395 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003396 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003397 int err;
3398
3399 BT_DBG("");
3400
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003401 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003402
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003403 /* If the old values are the same as the new ones just return a
3404 * direct command complete event.
3405 */
3406 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3407 !memcmp(hdev->short_name, cp->short_name,
3408 sizeof(hdev->short_name))) {
3409 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3410 data, len);
3411 goto failed;
3412 }
3413
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003414 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003415
Johan Hedbergb5235a62012-02-21 14:32:24 +02003416 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003417 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003418
3419 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003420 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003421 if (err < 0)
3422 goto failed;
3423
3424 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003425 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003426
Johan Hedbergb5235a62012-02-21 14:32:24 +02003427 goto failed;
3428 }
3429
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003430 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003431 if (!cmd) {
3432 err = -ENOMEM;
3433 goto failed;
3434 }
3435
Johan Hedberg13928972013-03-15 17:07:00 -05003436 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3437
Johan Hedberg890ea892013-03-15 17:06:52 -05003438 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003439
3440 if (lmp_bredr_capable(hdev)) {
3441 update_name(&req);
3442 update_eir(&req);
3443 }
3444
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003445 /* The name is stored in the scan response data and so
3446 * no need to udpate the advertising data here.
3447 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003448 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003449 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003450
Johan Hedberg13928972013-03-15 17:07:00 -05003451 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003452 if (err < 0)
3453 mgmt_pending_remove(cmd);
3454
3455failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003456 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003457 return err;
3458}
3459
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003460static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003461 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003462{
Szymon Jancc35938b2011-03-22 13:12:21 +01003463 struct pending_cmd *cmd;
3464 int err;
3465
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003466 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003467
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003468 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003469
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003470 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003471 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003472 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003473 goto unlock;
3474 }
3475
Andre Guedes9a1a1992012-07-24 15:03:48 -03003476 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003477 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003478 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003479 goto unlock;
3480 }
3481
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003482 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003483 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003485 goto unlock;
3486 }
3487
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003488 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003489 if (!cmd) {
3490 err = -ENOMEM;
3491 goto unlock;
3492 }
3493
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003494 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3495 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3496 0, NULL);
3497 else
3498 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3499
Szymon Jancc35938b2011-03-22 13:12:21 +01003500 if (err < 0)
3501 mgmt_pending_remove(cmd);
3502
3503unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003504 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003505 return err;
3506}
3507
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003508static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003509 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003510{
Szymon Janc2763eda2011-03-22 13:12:22 +01003511 int err;
3512
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003513 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003514
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003515 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003516
Marcel Holtmannec109112014-01-10 02:07:30 -08003517 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3518 struct mgmt_cp_add_remote_oob_data *cp = data;
3519 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003520
Marcel Holtmannec109112014-01-10 02:07:30 -08003521 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3522 cp->hash, cp->randomizer);
3523 if (err < 0)
3524 status = MGMT_STATUS_FAILED;
3525 else
3526 status = MGMT_STATUS_SUCCESS;
3527
3528 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3529 status, &cp->addr, sizeof(cp->addr));
3530 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3531 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3532 u8 status;
3533
3534 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3535 cp->hash192,
3536 cp->randomizer192,
3537 cp->hash256,
3538 cp->randomizer256);
3539 if (err < 0)
3540 status = MGMT_STATUS_FAILED;
3541 else
3542 status = MGMT_STATUS_SUCCESS;
3543
3544 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3545 status, &cp->addr, sizeof(cp->addr));
3546 } else {
3547 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3548 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3549 MGMT_STATUS_INVALID_PARAMS);
3550 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003551
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003552 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003553 return err;
3554}
3555
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003556static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003557 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003558{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003559 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003560 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003561 int err;
3562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003563 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003564
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003565 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003566
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003567 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003568 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003569 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003570 else
Szymon Janca6785be2012-12-13 15:11:21 +01003571 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003572
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003573 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003574 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003575
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003576 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003577 return err;
3578}
3579
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003580static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3581{
3582 struct pending_cmd *cmd;
3583 u8 type;
3584 int err;
3585
3586 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3587
3588 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3589 if (!cmd)
3590 return -ENOENT;
3591
3592 type = hdev->discovery.type;
3593
3594 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3595 &type, sizeof(type));
3596 mgmt_pending_remove(cmd);
3597
3598 return err;
3599}
3600
Andre Guedes7c307722013-04-30 15:29:28 -03003601static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3602{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003603 unsigned long timeout = 0;
3604
Andre Guedes7c307722013-04-30 15:29:28 -03003605 BT_DBG("status %d", status);
3606
3607 if (status) {
3608 hci_dev_lock(hdev);
3609 mgmt_start_discovery_failed(hdev, status);
3610 hci_dev_unlock(hdev);
3611 return;
3612 }
3613
3614 hci_dev_lock(hdev);
3615 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3616 hci_dev_unlock(hdev);
3617
3618 switch (hdev->discovery.type) {
3619 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003620 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003621 break;
3622
3623 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003624 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003625 break;
3626
3627 case DISCOV_TYPE_BREDR:
3628 break;
3629
3630 default:
3631 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3632 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003633
3634 if (!timeout)
3635 return;
3636
3637 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003638}
3639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003640static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003641 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003642{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003643 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003644 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003645 struct hci_cp_le_set_scan_param param_cp;
3646 struct hci_cp_le_set_scan_enable enable_cp;
3647 struct hci_cp_inquiry inq_cp;
3648 struct hci_request req;
3649 /* General inquiry access code (GIAC) */
3650 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003651 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003652 int err;
3653
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003654 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003655
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003656 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003657
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003658 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003659 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003660 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003661 goto failed;
3662 }
3663
Andre Guedes642be6c2012-03-21 00:03:37 -03003664 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3665 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3666 MGMT_STATUS_BUSY);
3667 goto failed;
3668 }
3669
Johan Hedbergff9ef572012-01-04 14:23:45 +02003670 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003671 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003672 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003673 goto failed;
3674 }
3675
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003676 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003677 if (!cmd) {
3678 err = -ENOMEM;
3679 goto failed;
3680 }
3681
Andre Guedes4aab14e2012-02-17 20:39:36 -03003682 hdev->discovery.type = cp->type;
3683
Andre Guedes7c307722013-04-30 15:29:28 -03003684 hci_req_init(&req, hdev);
3685
Andre Guedes4aab14e2012-02-17 20:39:36 -03003686 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003687 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003688 status = mgmt_bredr_support(hdev);
3689 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003690 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003691 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003692 mgmt_pending_remove(cmd);
3693 goto failed;
3694 }
3695
Andre Guedes7c307722013-04-30 15:29:28 -03003696 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3697 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3698 MGMT_STATUS_BUSY);
3699 mgmt_pending_remove(cmd);
3700 goto failed;
3701 }
3702
3703 hci_inquiry_cache_flush(hdev);
3704
3705 memset(&inq_cp, 0, sizeof(inq_cp));
3706 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003707 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003708 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003709 break;
3710
3711 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003712 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003713 status = mgmt_le_support(hdev);
3714 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003715 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003716 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003717 mgmt_pending_remove(cmd);
3718 goto failed;
3719 }
3720
Andre Guedes7c307722013-04-30 15:29:28 -03003721 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003722 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003723 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3724 MGMT_STATUS_NOT_SUPPORTED);
3725 mgmt_pending_remove(cmd);
3726 goto failed;
3727 }
3728
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003729 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003730 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3731 MGMT_STATUS_REJECTED);
3732 mgmt_pending_remove(cmd);
3733 goto failed;
3734 }
3735
Andre Guedesc54c3862014-02-26 20:21:50 -03003736 /* If controller is scanning, it means the background scanning
3737 * is running. Thus, we should temporarily stop it in order to
3738 * set the discovery scanning parameters.
3739 */
3740 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3741 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003742
3743 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003744
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003745 /* All active scans will be done with either a resolvable
3746 * private address (when privacy feature has been enabled)
3747 * or unresolvable private address.
3748 */
3749 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003750 if (err < 0) {
3751 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3752 MGMT_STATUS_FAILED);
3753 mgmt_pending_remove(cmd);
3754 goto failed;
3755 }
3756
Andre Guedes7c307722013-04-30 15:29:28 -03003757 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003758 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3759 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003760 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003761 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3762 &param_cp);
3763
3764 memset(&enable_cp, 0, sizeof(enable_cp));
3765 enable_cp.enable = LE_SCAN_ENABLE;
3766 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3767 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3768 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003769 break;
3770
Andre Guedesf39799f2012-02-17 20:39:35 -03003771 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003772 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3773 MGMT_STATUS_INVALID_PARAMS);
3774 mgmt_pending_remove(cmd);
3775 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003776 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003777
Andre Guedes7c307722013-04-30 15:29:28 -03003778 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003779 if (err < 0)
3780 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003781 else
3782 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003783
3784failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003785 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003786 return err;
3787}
3788
Andre Guedes1183fdc2013-04-30 15:29:35 -03003789static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3790{
3791 struct pending_cmd *cmd;
3792 int err;
3793
3794 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3795 if (!cmd)
3796 return -ENOENT;
3797
3798 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3799 &hdev->discovery.type, sizeof(hdev->discovery.type));
3800 mgmt_pending_remove(cmd);
3801
3802 return err;
3803}
3804
Andre Guedes0e05bba2013-04-30 15:29:33 -03003805static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3806{
3807 BT_DBG("status %d", status);
3808
3809 hci_dev_lock(hdev);
3810
3811 if (status) {
3812 mgmt_stop_discovery_failed(hdev, status);
3813 goto unlock;
3814 }
3815
3816 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3817
3818unlock:
3819 hci_dev_unlock(hdev);
3820}
3821
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003822static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003823 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003824{
Johan Hedbergd9306502012-02-20 23:25:18 +02003825 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003826 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003827 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003828 int err;
3829
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003830 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003831
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003832 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003833
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003834 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003835 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003836 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3837 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003838 goto unlock;
3839 }
3840
3841 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003842 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003843 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3844 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003845 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003846 }
3847
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003848 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003849 if (!cmd) {
3850 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003851 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003852 }
3853
Andre Guedes0e05bba2013-04-30 15:29:33 -03003854 hci_req_init(&req, hdev);
3855
Johan Hedberg21a60d32014-06-10 14:05:58 +03003856 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003857
Johan Hedberg21a60d32014-06-10 14:05:58 +03003858 err = hci_req_run(&req, stop_discovery_complete);
3859 if (!err) {
3860 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003861 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003862 }
3863
Johan Hedberg21a60d32014-06-10 14:05:58 +03003864 mgmt_pending_remove(cmd);
3865
3866 /* If no HCI commands were sent we're done */
3867 if (err == -ENODATA) {
3868 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3869 &mgmt_cp->type, sizeof(mgmt_cp->type));
3870 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3871 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003872
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003873unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003874 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003875 return err;
3876}
3877
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003878static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003879 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003880{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003881 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003882 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003883 int err;
3884
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003885 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003886
Johan Hedberg561aafb2012-01-04 13:31:59 +02003887 hci_dev_lock(hdev);
3888
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003889 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003890 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3891 MGMT_STATUS_FAILED, &cp->addr,
3892 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003893 goto failed;
3894 }
3895
Johan Hedberga198e7b2012-02-17 14:27:06 +02003896 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003897 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003898 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3899 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3900 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003901 goto failed;
3902 }
3903
3904 if (cp->name_known) {
3905 e->name_state = NAME_KNOWN;
3906 list_del(&e->list);
3907 } else {
3908 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003909 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003910 }
3911
Johan Hedberge3846622013-01-09 15:29:33 +02003912 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3913 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003914
3915failed:
3916 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003917 return err;
3918}
3919
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003920static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003921 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003922{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003923 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003924 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003925 int err;
3926
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003927 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003928
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003929 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003930 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3931 MGMT_STATUS_INVALID_PARAMS,
3932 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003933
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003934 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003935
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003936 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003937 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003938 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003939 goto done;
3940 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003941
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003942 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3943 sk);
3944 status = MGMT_STATUS_SUCCESS;
3945
3946done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003947 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003948 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003949
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003950 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003951
3952 return err;
3953}
3954
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003955static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003956 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003957{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003958 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003959 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003960 int err;
3961
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003962 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003963
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003964 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003965 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3966 MGMT_STATUS_INVALID_PARAMS,
3967 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003968
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003969 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003970
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003971 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003972 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003973 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003974 goto done;
3975 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003976
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003977 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3978 sk);
3979 status = MGMT_STATUS_SUCCESS;
3980
3981done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003982 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003983 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003984
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003985 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003986
3987 return err;
3988}
3989
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003990static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3991 u16 len)
3992{
3993 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003994 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003995 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003996 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003997
3998 BT_DBG("%s", hdev->name);
3999
Szymon Jancc72d4b82012-03-16 16:02:57 +01004000 source = __le16_to_cpu(cp->source);
4001
4002 if (source > 0x0002)
4003 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4004 MGMT_STATUS_INVALID_PARAMS);
4005
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004006 hci_dev_lock(hdev);
4007
Szymon Jancc72d4b82012-03-16 16:02:57 +01004008 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004009 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4010 hdev->devid_product = __le16_to_cpu(cp->product);
4011 hdev->devid_version = __le16_to_cpu(cp->version);
4012
4013 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4014
Johan Hedberg890ea892013-03-15 17:06:52 -05004015 hci_req_init(&req, hdev);
4016 update_eir(&req);
4017 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004018
4019 hci_dev_unlock(hdev);
4020
4021 return err;
4022}
4023
Johan Hedberg4375f102013-09-25 13:26:10 +03004024static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4025{
4026 struct cmd_lookup match = { NULL, hdev };
4027
4028 if (status) {
4029 u8 mgmt_err = mgmt_status(status);
4030
4031 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4032 cmd_status_rsp, &mgmt_err);
4033 return;
4034 }
4035
Johan Hedbergc93bd152014-07-08 15:07:48 +03004036 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4037 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4038 else
4039 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4040
Johan Hedberg4375f102013-09-25 13:26:10 +03004041 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4042 &match);
4043
4044 new_settings(hdev, match.sk);
4045
4046 if (match.sk)
4047 sock_put(match.sk);
4048}
4049
Marcel Holtmann21b51872013-10-10 09:47:53 -07004050static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4051 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004052{
4053 struct mgmt_mode *cp = data;
4054 struct pending_cmd *cmd;
4055 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004056 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004057 int err;
4058
4059 BT_DBG("request for %s", hdev->name);
4060
Johan Hedberge6fe7982013-10-02 15:45:22 +03004061 status = mgmt_le_support(hdev);
4062 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004063 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004064 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004065
4066 if (cp->val != 0x00 && cp->val != 0x01)
4067 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4068 MGMT_STATUS_INVALID_PARAMS);
4069
4070 hci_dev_lock(hdev);
4071
4072 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004073 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004074
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004075 /* The following conditions are ones which mean that we should
4076 * not do any HCI communication but directly send a mgmt
4077 * response to user space (after toggling the flag if
4078 * necessary).
4079 */
4080 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004081 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004082 bool changed = false;
4083
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004084 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4085 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004086 changed = true;
4087 }
4088
4089 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4090 if (err < 0)
4091 goto unlock;
4092
4093 if (changed)
4094 err = new_settings(hdev, sk);
4095
4096 goto unlock;
4097 }
4098
4099 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4100 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4101 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4102 MGMT_STATUS_BUSY);
4103 goto unlock;
4104 }
4105
4106 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4107 if (!cmd) {
4108 err = -ENOMEM;
4109 goto unlock;
4110 }
4111
4112 hci_req_init(&req, hdev);
4113
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004114 if (val)
4115 enable_advertising(&req);
4116 else
4117 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004118
4119 err = hci_req_run(&req, set_advertising_complete);
4120 if (err < 0)
4121 mgmt_pending_remove(cmd);
4122
4123unlock:
4124 hci_dev_unlock(hdev);
4125 return err;
4126}
4127
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004128static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4129 void *data, u16 len)
4130{
4131 struct mgmt_cp_set_static_address *cp = data;
4132 int err;
4133
4134 BT_DBG("%s", hdev->name);
4135
Marcel Holtmann62af4442013-10-02 22:10:32 -07004136 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004137 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004138 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004139
4140 if (hdev_is_powered(hdev))
4141 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4142 MGMT_STATUS_REJECTED);
4143
4144 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4145 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4146 return cmd_status(sk, hdev->id,
4147 MGMT_OP_SET_STATIC_ADDRESS,
4148 MGMT_STATUS_INVALID_PARAMS);
4149
4150 /* Two most significant bits shall be set */
4151 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4152 return cmd_status(sk, hdev->id,
4153 MGMT_OP_SET_STATIC_ADDRESS,
4154 MGMT_STATUS_INVALID_PARAMS);
4155 }
4156
4157 hci_dev_lock(hdev);
4158
4159 bacpy(&hdev->static_addr, &cp->bdaddr);
4160
4161 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4162
4163 hci_dev_unlock(hdev);
4164
4165 return err;
4166}
4167
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004168static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4169 void *data, u16 len)
4170{
4171 struct mgmt_cp_set_scan_params *cp = data;
4172 __u16 interval, window;
4173 int err;
4174
4175 BT_DBG("%s", hdev->name);
4176
4177 if (!lmp_le_capable(hdev))
4178 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4179 MGMT_STATUS_NOT_SUPPORTED);
4180
4181 interval = __le16_to_cpu(cp->interval);
4182
4183 if (interval < 0x0004 || interval > 0x4000)
4184 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4185 MGMT_STATUS_INVALID_PARAMS);
4186
4187 window = __le16_to_cpu(cp->window);
4188
4189 if (window < 0x0004 || window > 0x4000)
4190 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4191 MGMT_STATUS_INVALID_PARAMS);
4192
Marcel Holtmann899e1072013-10-14 09:55:32 -07004193 if (window > interval)
4194 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4195 MGMT_STATUS_INVALID_PARAMS);
4196
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004197 hci_dev_lock(hdev);
4198
4199 hdev->le_scan_interval = interval;
4200 hdev->le_scan_window = window;
4201
4202 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4203
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004204 /* If background scan is running, restart it so new parameters are
4205 * loaded.
4206 */
4207 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4208 hdev->discovery.state == DISCOVERY_STOPPED) {
4209 struct hci_request req;
4210
4211 hci_req_init(&req, hdev);
4212
4213 hci_req_add_le_scan_disable(&req);
4214 hci_req_add_le_passive_scan(&req);
4215
4216 hci_req_run(&req, NULL);
4217 }
4218
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004219 hci_dev_unlock(hdev);
4220
4221 return err;
4222}
4223
Johan Hedberg33e38b32013-03-15 17:07:05 -05004224static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4225{
4226 struct pending_cmd *cmd;
4227
4228 BT_DBG("status 0x%02x", status);
4229
4230 hci_dev_lock(hdev);
4231
4232 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4233 if (!cmd)
4234 goto unlock;
4235
4236 if (status) {
4237 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4238 mgmt_status(status));
4239 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004240 struct mgmt_mode *cp = cmd->param;
4241
4242 if (cp->val)
4243 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4244 else
4245 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4246
Johan Hedberg33e38b32013-03-15 17:07:05 -05004247 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4248 new_settings(hdev, cmd->sk);
4249 }
4250
4251 mgmt_pending_remove(cmd);
4252
4253unlock:
4254 hci_dev_unlock(hdev);
4255}
4256
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004257static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004258 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004259{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004260 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004261 struct pending_cmd *cmd;
4262 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004263 int err;
4264
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004265 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004266
Johan Hedberg56f87902013-10-02 13:43:13 +03004267 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4268 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004269 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4270 MGMT_STATUS_NOT_SUPPORTED);
4271
Johan Hedberga7e80f22013-01-09 16:05:19 +02004272 if (cp->val != 0x00 && cp->val != 0x01)
4273 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4274 MGMT_STATUS_INVALID_PARAMS);
4275
Johan Hedberg5400c042012-02-21 16:40:33 +02004276 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004277 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004278 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004279
4280 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004281 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004282 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004283
4284 hci_dev_lock(hdev);
4285
Johan Hedberg05cbf292013-03-15 17:07:07 -05004286 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4287 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4288 MGMT_STATUS_BUSY);
4289 goto unlock;
4290 }
4291
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004292 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4293 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4294 hdev);
4295 goto unlock;
4296 }
4297
Johan Hedberg33e38b32013-03-15 17:07:05 -05004298 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4299 data, len);
4300 if (!cmd) {
4301 err = -ENOMEM;
4302 goto unlock;
4303 }
4304
4305 hci_req_init(&req, hdev);
4306
Johan Hedberg406d7802013-03-15 17:07:09 -05004307 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004308
4309 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004310 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004311 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004312 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004313 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004314 }
4315
Johan Hedberg33e38b32013-03-15 17:07:05 -05004316unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004317 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004318
Antti Julkuf6422ec2011-06-22 13:11:56 +03004319 return err;
4320}
4321
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004322static void set_bredr_scan(struct hci_request *req)
4323{
4324 struct hci_dev *hdev = req->hdev;
4325 u8 scan = 0;
4326
4327 /* Ensure that fast connectable is disabled. This function will
4328 * not do anything if the page scan parameters are already what
4329 * they should be.
4330 */
4331 write_fast_connectable(req, false);
4332
4333 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4334 scan |= SCAN_PAGE;
4335 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4336 scan |= SCAN_INQUIRY;
4337
4338 if (scan)
4339 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4340}
4341
Johan Hedberg0663ca22013-10-02 13:43:14 +03004342static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4343{
4344 struct pending_cmd *cmd;
4345
4346 BT_DBG("status 0x%02x", status);
4347
4348 hci_dev_lock(hdev);
4349
4350 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4351 if (!cmd)
4352 goto unlock;
4353
4354 if (status) {
4355 u8 mgmt_err = mgmt_status(status);
4356
4357 /* We need to restore the flag if related HCI commands
4358 * failed.
4359 */
4360 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4361
4362 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4363 } else {
4364 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4365 new_settings(hdev, cmd->sk);
4366 }
4367
4368 mgmt_pending_remove(cmd);
4369
4370unlock:
4371 hci_dev_unlock(hdev);
4372}
4373
4374static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4375{
4376 struct mgmt_mode *cp = data;
4377 struct pending_cmd *cmd;
4378 struct hci_request req;
4379 int err;
4380
4381 BT_DBG("request for %s", hdev->name);
4382
4383 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4384 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4385 MGMT_STATUS_NOT_SUPPORTED);
4386
4387 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4388 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4389 MGMT_STATUS_REJECTED);
4390
4391 if (cp->val != 0x00 && cp->val != 0x01)
4392 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4393 MGMT_STATUS_INVALID_PARAMS);
4394
4395 hci_dev_lock(hdev);
4396
4397 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4398 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4399 goto unlock;
4400 }
4401
4402 if (!hdev_is_powered(hdev)) {
4403 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004404 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4405 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4406 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4407 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4408 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4409 }
4410
4411 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4412
4413 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4414 if (err < 0)
4415 goto unlock;
4416
4417 err = new_settings(hdev, sk);
4418 goto unlock;
4419 }
4420
4421 /* Reject disabling when powered on */
4422 if (!cp->val) {
4423 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4424 MGMT_STATUS_REJECTED);
4425 goto unlock;
4426 }
4427
4428 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4429 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4430 MGMT_STATUS_BUSY);
4431 goto unlock;
4432 }
4433
4434 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4435 if (!cmd) {
4436 err = -ENOMEM;
4437 goto unlock;
4438 }
4439
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004440 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004441 * generates the correct flags.
4442 */
4443 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4444
4445 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004446
4447 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4448 set_bredr_scan(&req);
4449
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004450 /* Since only the advertising data flags will change, there
4451 * is no need to update the scan response data.
4452 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004453 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004454
Johan Hedberg0663ca22013-10-02 13:43:14 +03004455 err = hci_req_run(&req, set_bredr_complete);
4456 if (err < 0)
4457 mgmt_pending_remove(cmd);
4458
4459unlock:
4460 hci_dev_unlock(hdev);
4461 return err;
4462}
4463
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004464static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4465 void *data, u16 len)
4466{
4467 struct mgmt_mode *cp = data;
4468 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004469 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004470 int err;
4471
4472 BT_DBG("request for %s", hdev->name);
4473
4474 status = mgmt_bredr_support(hdev);
4475 if (status)
4476 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4477 status);
4478
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004479 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004480 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004481 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4482 MGMT_STATUS_NOT_SUPPORTED);
4483
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004484 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004485 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4486 MGMT_STATUS_INVALID_PARAMS);
4487
4488 hci_dev_lock(hdev);
4489
4490 if (!hdev_is_powered(hdev)) {
4491 bool changed;
4492
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004493 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004494 changed = !test_and_set_bit(HCI_SC_ENABLED,
4495 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004496 if (cp->val == 0x02)
4497 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4498 else
4499 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4500 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004501 changed = test_and_clear_bit(HCI_SC_ENABLED,
4502 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004503 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4504 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004505
4506 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4507 if (err < 0)
4508 goto failed;
4509
4510 if (changed)
4511 err = new_settings(hdev, sk);
4512
4513 goto failed;
4514 }
4515
4516 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4517 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4518 MGMT_STATUS_BUSY);
4519 goto failed;
4520 }
4521
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004522 val = !!cp->val;
4523
4524 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4525 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004526 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4527 goto failed;
4528 }
4529
4530 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4531 if (!cmd) {
4532 err = -ENOMEM;
4533 goto failed;
4534 }
4535
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004536 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004537 if (err < 0) {
4538 mgmt_pending_remove(cmd);
4539 goto failed;
4540 }
4541
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004542 if (cp->val == 0x02)
4543 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4544 else
4545 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4546
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004547failed:
4548 hci_dev_unlock(hdev);
4549 return err;
4550}
4551
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004552static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4553 void *data, u16 len)
4554{
4555 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004556 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004557 int err;
4558
4559 BT_DBG("request for %s", hdev->name);
4560
Johan Hedbergb97109792014-06-24 14:00:28 +03004561 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004562 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4563 MGMT_STATUS_INVALID_PARAMS);
4564
4565 hci_dev_lock(hdev);
4566
4567 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004568 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4569 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004570 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004571 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4572 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004573
Johan Hedbergb97109792014-06-24 14:00:28 +03004574 if (cp->val == 0x02)
4575 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4576 &hdev->dev_flags);
4577 else
4578 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4579 &hdev->dev_flags);
4580
4581 if (hdev_is_powered(hdev) && use_changed &&
4582 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4583 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4584 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4585 sizeof(mode), &mode);
4586 }
4587
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004588 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4589 if (err < 0)
4590 goto unlock;
4591
4592 if (changed)
4593 err = new_settings(hdev, sk);
4594
4595unlock:
4596 hci_dev_unlock(hdev);
4597 return err;
4598}
4599
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004600static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4601 u16 len)
4602{
4603 struct mgmt_cp_set_privacy *cp = cp_data;
4604 bool changed;
4605 int err;
4606
4607 BT_DBG("request for %s", hdev->name);
4608
4609 if (!lmp_le_capable(hdev))
4610 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4611 MGMT_STATUS_NOT_SUPPORTED);
4612
4613 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4614 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4615 MGMT_STATUS_INVALID_PARAMS);
4616
4617 if (hdev_is_powered(hdev))
4618 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4619 MGMT_STATUS_REJECTED);
4620
4621 hci_dev_lock(hdev);
4622
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004623 /* If user space supports this command it is also expected to
4624 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4625 */
4626 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4627
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004628 if (cp->privacy) {
4629 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4630 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4631 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4632 } else {
4633 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4634 memset(hdev->irk, 0, sizeof(hdev->irk));
4635 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4636 }
4637
4638 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4639 if (err < 0)
4640 goto unlock;
4641
4642 if (changed)
4643 err = new_settings(hdev, sk);
4644
4645unlock:
4646 hci_dev_unlock(hdev);
4647 return err;
4648}
4649
Johan Hedberg41edf162014-02-18 10:19:35 +02004650static bool irk_is_valid(struct mgmt_irk_info *irk)
4651{
4652 switch (irk->addr.type) {
4653 case BDADDR_LE_PUBLIC:
4654 return true;
4655
4656 case BDADDR_LE_RANDOM:
4657 /* Two most significant bits shall be set */
4658 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4659 return false;
4660 return true;
4661 }
4662
4663 return false;
4664}
4665
4666static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4667 u16 len)
4668{
4669 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004670 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4671 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004672 u16 irk_count, expected_len;
4673 int i, err;
4674
4675 BT_DBG("request for %s", hdev->name);
4676
4677 if (!lmp_le_capable(hdev))
4678 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4679 MGMT_STATUS_NOT_SUPPORTED);
4680
4681 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004682 if (irk_count > max_irk_count) {
4683 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4684 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4685 MGMT_STATUS_INVALID_PARAMS);
4686 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004687
4688 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4689 if (expected_len != len) {
4690 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004691 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004692 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4693 MGMT_STATUS_INVALID_PARAMS);
4694 }
4695
4696 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4697
4698 for (i = 0; i < irk_count; i++) {
4699 struct mgmt_irk_info *key = &cp->irks[i];
4700
4701 if (!irk_is_valid(key))
4702 return cmd_status(sk, hdev->id,
4703 MGMT_OP_LOAD_IRKS,
4704 MGMT_STATUS_INVALID_PARAMS);
4705 }
4706
4707 hci_dev_lock(hdev);
4708
4709 hci_smp_irks_clear(hdev);
4710
4711 for (i = 0; i < irk_count; i++) {
4712 struct mgmt_irk_info *irk = &cp->irks[i];
4713 u8 addr_type;
4714
4715 if (irk->addr.type == BDADDR_LE_PUBLIC)
4716 addr_type = ADDR_LE_DEV_PUBLIC;
4717 else
4718 addr_type = ADDR_LE_DEV_RANDOM;
4719
4720 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4721 BDADDR_ANY);
4722 }
4723
4724 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4725
4726 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4727
4728 hci_dev_unlock(hdev);
4729
4730 return err;
4731}
4732
Johan Hedberg3f706b72013-01-20 14:27:16 +02004733static bool ltk_is_valid(struct mgmt_ltk_info *key)
4734{
4735 if (key->master != 0x00 && key->master != 0x01)
4736 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004737
4738 switch (key->addr.type) {
4739 case BDADDR_LE_PUBLIC:
4740 return true;
4741
4742 case BDADDR_LE_RANDOM:
4743 /* Two most significant bits shall be set */
4744 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4745 return false;
4746 return true;
4747 }
4748
4749 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004750}
4751
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004752static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004753 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004754{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004755 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004756 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4757 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004758 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004759 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004760
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004761 BT_DBG("request for %s", hdev->name);
4762
4763 if (!lmp_le_capable(hdev))
4764 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4765 MGMT_STATUS_NOT_SUPPORTED);
4766
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004767 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004768 if (key_count > max_key_count) {
4769 BT_ERR("load_ltks: too big key_count value %u", key_count);
4770 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4771 MGMT_STATUS_INVALID_PARAMS);
4772 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004773
4774 expected_len = sizeof(*cp) + key_count *
4775 sizeof(struct mgmt_ltk_info);
4776 if (expected_len != len) {
4777 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004778 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004779 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004780 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004781 }
4782
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004783 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004784
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004785 for (i = 0; i < key_count; i++) {
4786 struct mgmt_ltk_info *key = &cp->keys[i];
4787
Johan Hedberg3f706b72013-01-20 14:27:16 +02004788 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004789 return cmd_status(sk, hdev->id,
4790 MGMT_OP_LOAD_LONG_TERM_KEYS,
4791 MGMT_STATUS_INVALID_PARAMS);
4792 }
4793
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004794 hci_dev_lock(hdev);
4795
4796 hci_smp_ltks_clear(hdev);
4797
4798 for (i = 0; i < key_count; i++) {
4799 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004800 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004801
4802 if (key->addr.type == BDADDR_LE_PUBLIC)
4803 addr_type = ADDR_LE_DEV_PUBLIC;
4804 else
4805 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004806
4807 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004808 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004809 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004810 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004811
Johan Hedberg61b43352014-05-29 19:36:53 +03004812 switch (key->type) {
4813 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004814 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004815 break;
4816 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004817 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004818 break;
4819 default:
4820 continue;
4821 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004822
Johan Hedberg35d70272014-02-19 14:57:47 +02004823 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004824 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004825 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004826 }
4827
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004828 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4829 NULL, 0);
4830
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004831 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004832
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004833 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004834}
4835
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004836struct cmd_conn_lookup {
4837 struct hci_conn *conn;
4838 bool valid_tx_power;
4839 u8 mgmt_status;
4840};
4841
4842static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4843{
4844 struct cmd_conn_lookup *match = data;
4845 struct mgmt_cp_get_conn_info *cp;
4846 struct mgmt_rp_get_conn_info rp;
4847 struct hci_conn *conn = cmd->user_data;
4848
4849 if (conn != match->conn)
4850 return;
4851
4852 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4853
4854 memset(&rp, 0, sizeof(rp));
4855 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4856 rp.addr.type = cp->addr.type;
4857
4858 if (!match->mgmt_status) {
4859 rp.rssi = conn->rssi;
4860
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004861 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004862 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004863 rp.max_tx_power = conn->max_tx_power;
4864 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004865 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004866 rp.max_tx_power = HCI_TX_POWER_INVALID;
4867 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004868 }
4869
4870 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4871 match->mgmt_status, &rp, sizeof(rp));
4872
4873 hci_conn_drop(conn);
4874
4875 mgmt_pending_remove(cmd);
4876}
4877
4878static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4879{
4880 struct hci_cp_read_rssi *cp;
4881 struct hci_conn *conn;
4882 struct cmd_conn_lookup match;
4883 u16 handle;
4884
4885 BT_DBG("status 0x%02x", status);
4886
4887 hci_dev_lock(hdev);
4888
4889 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004890 * otherwise we assume it's not valid. At the moment we assume that
4891 * either both or none of current and max values are valid to keep code
4892 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004893 */
4894 match.valid_tx_power = !status;
4895
4896 /* Commands sent in request are either Read RSSI or Read Transmit Power
4897 * Level so we check which one was last sent to retrieve connection
4898 * handle. Both commands have handle as first parameter so it's safe to
4899 * cast data on the same command struct.
4900 *
4901 * First command sent is always Read RSSI and we fail only if it fails.
4902 * In other case we simply override error to indicate success as we
4903 * already remembered if TX power value is actually valid.
4904 */
4905 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4906 if (!cp) {
4907 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4908 status = 0;
4909 }
4910
4911 if (!cp) {
4912 BT_ERR("invalid sent_cmd in response");
4913 goto unlock;
4914 }
4915
4916 handle = __le16_to_cpu(cp->handle);
4917 conn = hci_conn_hash_lookup_handle(hdev, handle);
4918 if (!conn) {
4919 BT_ERR("unknown handle (%d) in response", handle);
4920 goto unlock;
4921 }
4922
4923 match.conn = conn;
4924 match.mgmt_status = mgmt_status(status);
4925
4926 /* Cache refresh is complete, now reply for mgmt request for given
4927 * connection only.
4928 */
4929 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4930 get_conn_info_complete, &match);
4931
4932unlock:
4933 hci_dev_unlock(hdev);
4934}
4935
4936static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4937 u16 len)
4938{
4939 struct mgmt_cp_get_conn_info *cp = data;
4940 struct mgmt_rp_get_conn_info rp;
4941 struct hci_conn *conn;
4942 unsigned long conn_info_age;
4943 int err = 0;
4944
4945 BT_DBG("%s", hdev->name);
4946
4947 memset(&rp, 0, sizeof(rp));
4948 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4949 rp.addr.type = cp->addr.type;
4950
4951 if (!bdaddr_type_is_valid(cp->addr.type))
4952 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4953 MGMT_STATUS_INVALID_PARAMS,
4954 &rp, sizeof(rp));
4955
4956 hci_dev_lock(hdev);
4957
4958 if (!hdev_is_powered(hdev)) {
4959 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4960 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4961 goto unlock;
4962 }
4963
4964 if (cp->addr.type == BDADDR_BREDR)
4965 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4966 &cp->addr.bdaddr);
4967 else
4968 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4969
4970 if (!conn || conn->state != BT_CONNECTED) {
4971 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4972 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4973 goto unlock;
4974 }
4975
4976 /* To avoid client trying to guess when to poll again for information we
4977 * calculate conn info age as random value between min/max set in hdev.
4978 */
4979 conn_info_age = hdev->conn_info_min_age +
4980 prandom_u32_max(hdev->conn_info_max_age -
4981 hdev->conn_info_min_age);
4982
4983 /* Query controller to refresh cached values if they are too old or were
4984 * never read.
4985 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004986 if (time_after(jiffies, conn->conn_info_timestamp +
4987 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004988 !conn->conn_info_timestamp) {
4989 struct hci_request req;
4990 struct hci_cp_read_tx_power req_txp_cp;
4991 struct hci_cp_read_rssi req_rssi_cp;
4992 struct pending_cmd *cmd;
4993
4994 hci_req_init(&req, hdev);
4995 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4996 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4997 &req_rssi_cp);
4998
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004999 /* For LE links TX power does not change thus we don't need to
5000 * query for it once value is known.
5001 */
5002 if (!bdaddr_type_is_le(cp->addr.type) ||
5003 conn->tx_power == HCI_TX_POWER_INVALID) {
5004 req_txp_cp.handle = cpu_to_le16(conn->handle);
5005 req_txp_cp.type = 0x00;
5006 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5007 sizeof(req_txp_cp), &req_txp_cp);
5008 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005009
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005010 /* Max TX power needs to be read only once per connection */
5011 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5012 req_txp_cp.handle = cpu_to_le16(conn->handle);
5013 req_txp_cp.type = 0x01;
5014 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5015 sizeof(req_txp_cp), &req_txp_cp);
5016 }
5017
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005018 err = hci_req_run(&req, conn_info_refresh_complete);
5019 if (err < 0)
5020 goto unlock;
5021
5022 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5023 data, len);
5024 if (!cmd) {
5025 err = -ENOMEM;
5026 goto unlock;
5027 }
5028
5029 hci_conn_hold(conn);
5030 cmd->user_data = conn;
5031
5032 conn->conn_info_timestamp = jiffies;
5033 } else {
5034 /* Cache is valid, just reply with values cached in hci_conn */
5035 rp.rssi = conn->rssi;
5036 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005037 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005038
5039 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5040 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5041 }
5042
5043unlock:
5044 hci_dev_unlock(hdev);
5045 return err;
5046}
5047
Johan Hedberg95868422014-06-28 17:54:07 +03005048static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5049{
5050 struct mgmt_cp_get_clock_info *cp;
5051 struct mgmt_rp_get_clock_info rp;
5052 struct hci_cp_read_clock *hci_cp;
5053 struct pending_cmd *cmd;
5054 struct hci_conn *conn;
5055
5056 BT_DBG("%s status %u", hdev->name, status);
5057
5058 hci_dev_lock(hdev);
5059
5060 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5061 if (!hci_cp)
5062 goto unlock;
5063
5064 if (hci_cp->which) {
5065 u16 handle = __le16_to_cpu(hci_cp->handle);
5066 conn = hci_conn_hash_lookup_handle(hdev, handle);
5067 } else {
5068 conn = NULL;
5069 }
5070
5071 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5072 if (!cmd)
5073 goto unlock;
5074
5075 cp = cmd->param;
5076
5077 memset(&rp, 0, sizeof(rp));
5078 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5079
5080 if (status)
5081 goto send_rsp;
5082
5083 rp.local_clock = cpu_to_le32(hdev->clock);
5084
5085 if (conn) {
5086 rp.piconet_clock = cpu_to_le32(conn->clock);
5087 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5088 }
5089
5090send_rsp:
5091 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5092 &rp, sizeof(rp));
5093 mgmt_pending_remove(cmd);
5094 if (conn)
5095 hci_conn_drop(conn);
5096
5097unlock:
5098 hci_dev_unlock(hdev);
5099}
5100
5101static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5102 u16 len)
5103{
5104 struct mgmt_cp_get_clock_info *cp = data;
5105 struct mgmt_rp_get_clock_info rp;
5106 struct hci_cp_read_clock hci_cp;
5107 struct pending_cmd *cmd;
5108 struct hci_request req;
5109 struct hci_conn *conn;
5110 int err;
5111
5112 BT_DBG("%s", hdev->name);
5113
5114 memset(&rp, 0, sizeof(rp));
5115 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5116 rp.addr.type = cp->addr.type;
5117
5118 if (cp->addr.type != BDADDR_BREDR)
5119 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5120 MGMT_STATUS_INVALID_PARAMS,
5121 &rp, sizeof(rp));
5122
5123 hci_dev_lock(hdev);
5124
5125 if (!hdev_is_powered(hdev)) {
5126 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5127 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5128 goto unlock;
5129 }
5130
5131 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5132 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5133 &cp->addr.bdaddr);
5134 if (!conn || conn->state != BT_CONNECTED) {
5135 err = cmd_complete(sk, hdev->id,
5136 MGMT_OP_GET_CLOCK_INFO,
5137 MGMT_STATUS_NOT_CONNECTED,
5138 &rp, sizeof(rp));
5139 goto unlock;
5140 }
5141 } else {
5142 conn = NULL;
5143 }
5144
5145 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5146 if (!cmd) {
5147 err = -ENOMEM;
5148 goto unlock;
5149 }
5150
5151 hci_req_init(&req, hdev);
5152
5153 memset(&hci_cp, 0, sizeof(hci_cp));
5154 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5155
5156 if (conn) {
5157 hci_conn_hold(conn);
5158 cmd->user_data = conn;
5159
5160 hci_cp.handle = cpu_to_le16(conn->handle);
5161 hci_cp.which = 0x01; /* Piconet clock */
5162 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5163 }
5164
5165 err = hci_req_run(&req, get_clock_info_complete);
5166 if (err < 0)
5167 mgmt_pending_remove(cmd);
5168
5169unlock:
5170 hci_dev_unlock(hdev);
5171 return err;
5172}
5173
Marcel Holtmann8afef092014-06-29 22:28:34 +02005174static void device_added(struct sock *sk, struct hci_dev *hdev,
5175 bdaddr_t *bdaddr, u8 type, u8 action)
5176{
5177 struct mgmt_ev_device_added ev;
5178
5179 bacpy(&ev.addr.bdaddr, bdaddr);
5180 ev.addr.type = type;
5181 ev.action = action;
5182
5183 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5184}
5185
Marcel Holtmann2faade52014-06-29 19:44:03 +02005186static int add_device(struct sock *sk, struct hci_dev *hdev,
5187 void *data, u16 len)
5188{
5189 struct mgmt_cp_add_device *cp = data;
5190 u8 auto_conn, addr_type;
5191 int err;
5192
5193 BT_DBG("%s", hdev->name);
5194
5195 if (!bdaddr_type_is_le(cp->addr.type) ||
5196 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5197 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5198 MGMT_STATUS_INVALID_PARAMS,
5199 &cp->addr, sizeof(cp->addr));
5200
5201 if (cp->action != 0x00 && cp->action != 0x01)
5202 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5203 MGMT_STATUS_INVALID_PARAMS,
5204 &cp->addr, sizeof(cp->addr));
5205
5206 hci_dev_lock(hdev);
5207
5208 if (cp->addr.type == BDADDR_LE_PUBLIC)
5209 addr_type = ADDR_LE_DEV_PUBLIC;
5210 else
5211 addr_type = ADDR_LE_DEV_RANDOM;
5212
5213 if (cp->action)
5214 auto_conn = HCI_AUTO_CONN_ALWAYS;
5215 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005216 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005217
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005218 /* If the connection parameters don't exist for this device,
5219 * they will be created and configured with defaults.
5220 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005221 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5222 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005223 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5224 MGMT_STATUS_FAILED,
5225 &cp->addr, sizeof(cp->addr));
5226 goto unlock;
5227 }
5228
Marcel Holtmann8afef092014-06-29 22:28:34 +02005229 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5230
Marcel Holtmann2faade52014-06-29 19:44:03 +02005231 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5232 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5233
5234unlock:
5235 hci_dev_unlock(hdev);
5236 return err;
5237}
5238
Marcel Holtmann8afef092014-06-29 22:28:34 +02005239static void device_removed(struct sock *sk, struct hci_dev *hdev,
5240 bdaddr_t *bdaddr, u8 type)
5241{
5242 struct mgmt_ev_device_removed ev;
5243
5244 bacpy(&ev.addr.bdaddr, bdaddr);
5245 ev.addr.type = type;
5246
5247 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5248}
5249
Marcel Holtmann2faade52014-06-29 19:44:03 +02005250static int remove_device(struct sock *sk, struct hci_dev *hdev,
5251 void *data, u16 len)
5252{
5253 struct mgmt_cp_remove_device *cp = data;
5254 int err;
5255
5256 BT_DBG("%s", hdev->name);
5257
5258 hci_dev_lock(hdev);
5259
5260 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005261 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005262 u8 addr_type;
5263
5264 if (!bdaddr_type_is_le(cp->addr.type)) {
5265 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5266 MGMT_STATUS_INVALID_PARAMS,
5267 &cp->addr, sizeof(cp->addr));
5268 goto unlock;
5269 }
5270
5271 if (cp->addr.type == BDADDR_LE_PUBLIC)
5272 addr_type = ADDR_LE_DEV_PUBLIC;
5273 else
5274 addr_type = ADDR_LE_DEV_RANDOM;
5275
Johan Hedbergc71593d2014-07-02 17:37:28 +03005276 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5277 addr_type);
5278 if (!params) {
5279 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5280 MGMT_STATUS_INVALID_PARAMS,
5281 &cp->addr, sizeof(cp->addr));
5282 goto unlock;
5283 }
5284
5285 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5286 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5287 MGMT_STATUS_INVALID_PARAMS,
5288 &cp->addr, sizeof(cp->addr));
5289 goto unlock;
5290 }
5291
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005292 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005293 list_del(&params->list);
5294 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005295 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005296
5297 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005298 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005299 struct hci_conn_params *p, *tmp;
5300
Marcel Holtmann2faade52014-06-29 19:44:03 +02005301 if (cp->addr.type) {
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
Johan Hedberg19de0822014-07-06 13:06:51 +03005308 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5309 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5310 continue;
5311 device_removed(sk, hdev, &p->addr, p->addr_type);
5312 list_del(&p->action);
5313 list_del(&p->list);
5314 kfree(p);
5315 }
5316
5317 BT_DBG("All LE connection parameters were removed");
5318
5319 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005320 }
5321
5322 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5323 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5324
5325unlock:
5326 hci_dev_unlock(hdev);
5327 return err;
5328}
5329
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005330static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5331 u16 len)
5332{
5333 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005334 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5335 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005336 u16 param_count, expected_len;
5337 int i;
5338
5339 if (!lmp_le_capable(hdev))
5340 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5341 MGMT_STATUS_NOT_SUPPORTED);
5342
5343 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005344 if (param_count > max_param_count) {
5345 BT_ERR("load_conn_param: too big param_count value %u",
5346 param_count);
5347 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5348 MGMT_STATUS_INVALID_PARAMS);
5349 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005350
5351 expected_len = sizeof(*cp) + param_count *
5352 sizeof(struct mgmt_conn_param);
5353 if (expected_len != len) {
5354 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5355 expected_len, len);
5356 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5357 MGMT_STATUS_INVALID_PARAMS);
5358 }
5359
5360 BT_DBG("%s param_count %u", hdev->name, param_count);
5361
5362 hci_dev_lock(hdev);
5363
5364 hci_conn_params_clear_disabled(hdev);
5365
5366 for (i = 0; i < param_count; i++) {
5367 struct mgmt_conn_param *param = &cp->params[i];
5368 struct hci_conn_params *hci_param;
5369 u16 min, max, latency, timeout;
5370 u8 addr_type;
5371
5372 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5373 param->addr.type);
5374
5375 if (param->addr.type == BDADDR_LE_PUBLIC) {
5376 addr_type = ADDR_LE_DEV_PUBLIC;
5377 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5378 addr_type = ADDR_LE_DEV_RANDOM;
5379 } else {
5380 BT_ERR("Ignoring invalid connection parameters");
5381 continue;
5382 }
5383
5384 min = le16_to_cpu(param->min_interval);
5385 max = le16_to_cpu(param->max_interval);
5386 latency = le16_to_cpu(param->latency);
5387 timeout = le16_to_cpu(param->timeout);
5388
5389 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5390 min, max, latency, timeout);
5391
5392 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5393 BT_ERR("Ignoring invalid connection parameters");
5394 continue;
5395 }
5396
5397 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5398 addr_type);
5399 if (!hci_param) {
5400 BT_ERR("Failed to add connection parameters");
5401 continue;
5402 }
5403
5404 hci_param->conn_min_interval = min;
5405 hci_param->conn_max_interval = max;
5406 hci_param->conn_latency = latency;
5407 hci_param->supervision_timeout = timeout;
5408 }
5409
5410 hci_dev_unlock(hdev);
5411
5412 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5413}
5414
Marcel Holtmanndbece372014-07-04 18:11:55 +02005415static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5416 void *data, u16 len)
5417{
5418 struct mgmt_cp_set_external_config *cp = data;
5419 bool changed;
5420 int err;
5421
5422 BT_DBG("%s", hdev->name);
5423
5424 if (hdev_is_powered(hdev))
5425 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5426 MGMT_STATUS_REJECTED);
5427
5428 if (cp->config != 0x00 && cp->config != 0x01)
5429 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5430 MGMT_STATUS_INVALID_PARAMS);
5431
5432 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5433 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5434 MGMT_STATUS_NOT_SUPPORTED);
5435
5436 hci_dev_lock(hdev);
5437
5438 if (cp->config)
5439 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5440 &hdev->dev_flags);
5441 else
5442 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5443 &hdev->dev_flags);
5444
5445 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5446 if (err < 0)
5447 goto unlock;
5448
5449 if (!changed)
5450 goto unlock;
5451
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005452 err = new_options(hdev, sk);
5453
Marcel Holtmanndbece372014-07-04 18:11:55 +02005454 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5455 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005456
5457 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5458 set_bit(HCI_CONFIG, &hdev->dev_flags);
5459 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5460
5461 queue_work(hdev->req_workqueue, &hdev->power_on);
5462 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005463 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005464 mgmt_index_added(hdev);
5465 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005466 }
5467
5468unlock:
5469 hci_dev_unlock(hdev);
5470 return err;
5471}
5472
Marcel Holtmann9713c172014-07-06 12:11:15 +02005473static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5474 void *data, u16 len)
5475{
5476 struct mgmt_cp_set_public_address *cp = data;
5477 bool changed;
5478 int err;
5479
5480 BT_DBG("%s", hdev->name);
5481
5482 if (hdev_is_powered(hdev))
5483 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5484 MGMT_STATUS_REJECTED);
5485
5486 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5487 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5488 MGMT_STATUS_INVALID_PARAMS);
5489
5490 if (!hdev->set_bdaddr)
5491 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5492 MGMT_STATUS_NOT_SUPPORTED);
5493
5494 hci_dev_lock(hdev);
5495
5496 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5497 bacpy(&hdev->public_addr, &cp->bdaddr);
5498
5499 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5500 if (err < 0)
5501 goto unlock;
5502
5503 if (!changed)
5504 goto unlock;
5505
5506 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5507 err = new_options(hdev, sk);
5508
5509 if (is_configured(hdev)) {
5510 mgmt_index_removed(hdev);
5511
5512 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5513
5514 set_bit(HCI_CONFIG, &hdev->dev_flags);
5515 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5516
5517 queue_work(hdev->req_workqueue, &hdev->power_on);
5518 }
5519
5520unlock:
5521 hci_dev_unlock(hdev);
5522 return err;
5523}
5524
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005525static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005526 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5527 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005528 bool var_len;
5529 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005530} mgmt_handlers[] = {
5531 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005532 { read_version, false, MGMT_READ_VERSION_SIZE },
5533 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5534 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5535 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5536 { set_powered, false, MGMT_SETTING_SIZE },
5537 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5538 { set_connectable, false, MGMT_SETTING_SIZE },
5539 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5540 { set_pairable, false, MGMT_SETTING_SIZE },
5541 { set_link_security, false, MGMT_SETTING_SIZE },
5542 { set_ssp, false, MGMT_SETTING_SIZE },
5543 { set_hs, false, MGMT_SETTING_SIZE },
5544 { set_le, false, MGMT_SETTING_SIZE },
5545 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5546 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5547 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5548 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5549 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5550 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5551 { disconnect, false, MGMT_DISCONNECT_SIZE },
5552 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5553 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5554 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5555 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5556 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5557 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5558 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5559 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5560 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5561 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5562 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5563 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005564 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005565 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5566 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5567 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5568 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5569 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5570 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005571 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005572 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005573 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005574 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005575 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005576 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005577 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005578 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005579 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005580 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005581 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005582 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5583 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005584 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5585 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005586 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005587 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005588 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005589};
5590
Johan Hedberg03811012010-12-08 00:21:06 +02005591int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5592{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005593 void *buf;
5594 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005595 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005596 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005597 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005598 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005599 int err;
5600
5601 BT_DBG("got %zu bytes", msglen);
5602
5603 if (msglen < sizeof(*hdr))
5604 return -EINVAL;
5605
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005606 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005607 if (!buf)
5608 return -ENOMEM;
5609
5610 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5611 err = -EFAULT;
5612 goto done;
5613 }
5614
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005615 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005616 opcode = __le16_to_cpu(hdr->opcode);
5617 index = __le16_to_cpu(hdr->index);
5618 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005619
5620 if (len != msglen - sizeof(*hdr)) {
5621 err = -EINVAL;
5622 goto done;
5623 }
5624
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005625 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005626 hdev = hci_dev_get(index);
5627 if (!hdev) {
5628 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005629 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005630 goto done;
5631 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005632
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005633 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005634 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005635 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005636 err = cmd_status(sk, index, opcode,
5637 MGMT_STATUS_INVALID_INDEX);
5638 goto done;
5639 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005640
5641 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005642 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005643 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5644 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005645 err = cmd_status(sk, index, opcode,
5646 MGMT_STATUS_INVALID_INDEX);
5647 goto done;
5648 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005649 }
5650
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005651 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005652 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005653 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005654 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005655 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005656 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005657 }
5658
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005659 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5660 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5661 err = cmd_status(sk, index, opcode,
5662 MGMT_STATUS_INVALID_INDEX);
5663 goto done;
5664 }
5665
5666 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5667 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005668 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005669 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005670 goto done;
5671 }
5672
Johan Hedbergbe22b542012-03-01 22:24:41 +02005673 handler = &mgmt_handlers[opcode];
5674
5675 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005676 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005677 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005678 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005679 goto done;
5680 }
5681
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005682 if (hdev)
5683 mgmt_init_hdev(sk, hdev);
5684
5685 cp = buf + sizeof(*hdr);
5686
Johan Hedbergbe22b542012-03-01 22:24:41 +02005687 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005688 if (err < 0)
5689 goto done;
5690
Johan Hedberg03811012010-12-08 00:21:06 +02005691 err = msglen;
5692
5693done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005694 if (hdev)
5695 hci_dev_put(hdev);
5696
Johan Hedberg03811012010-12-08 00:21:06 +02005697 kfree(buf);
5698 return err;
5699}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005700
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005701void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005702{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005703 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005704 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005705
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005706 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5707 return;
5708
5709 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5710 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5711 else
5712 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005713}
5714
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005715void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005716{
Johan Hedberg5f159032012-03-02 03:13:19 +02005717 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005718
Marcel Holtmann1514b892013-10-06 08:25:01 -07005719 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005720 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005721
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005722 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5723 return;
5724
Johan Hedberg744cf192011-11-08 20:40:14 +02005725 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005726
Marcel Holtmannedd38962014-07-02 21:30:55 +02005727 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5728 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5729 else
5730 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005731}
5732
Andre Guedes6046dc32014-02-26 20:21:51 -03005733/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005734static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005735{
5736 struct hci_conn_params *p;
5737
5738 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005739 /* Needed for AUTO_OFF case where might not "really"
5740 * have been powered off.
5741 */
5742 list_del_init(&p->action);
5743
5744 switch (p->auto_connect) {
5745 case HCI_AUTO_CONN_ALWAYS:
5746 list_add(&p->action, &hdev->pend_le_conns);
5747 break;
5748 case HCI_AUTO_CONN_REPORT:
5749 list_add(&p->action, &hdev->pend_le_reports);
5750 break;
5751 default:
5752 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005753 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005754 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005755
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005756 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005757}
5758
Johan Hedberg229ab392013-03-15 17:06:53 -05005759static void powered_complete(struct hci_dev *hdev, u8 status)
5760{
5761 struct cmd_lookup match = { NULL, hdev };
5762
5763 BT_DBG("status 0x%02x", status);
5764
5765 hci_dev_lock(hdev);
5766
Johan Hedbergd7347f32014-07-04 12:37:23 +03005767 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005768
Johan Hedberg229ab392013-03-15 17:06:53 -05005769 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5770
5771 new_settings(hdev, match.sk);
5772
5773 hci_dev_unlock(hdev);
5774
5775 if (match.sk)
5776 sock_put(match.sk);
5777}
5778
Johan Hedberg70da6242013-03-15 17:06:51 -05005779static int powered_update_hci(struct hci_dev *hdev)
5780{
Johan Hedberg890ea892013-03-15 17:06:52 -05005781 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005782 u8 link_sec;
5783
Johan Hedberg890ea892013-03-15 17:06:52 -05005784 hci_req_init(&req, hdev);
5785
Johan Hedberg70da6242013-03-15 17:06:51 -05005786 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5787 !lmp_host_ssp_capable(hdev)) {
5788 u8 ssp = 1;
5789
Johan Hedberg890ea892013-03-15 17:06:52 -05005790 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005791 }
5792
Johan Hedbergc73eee92013-04-19 18:35:21 +03005793 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5794 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005795 struct hci_cp_write_le_host_supported cp;
5796
5797 cp.le = 1;
5798 cp.simul = lmp_le_br_capable(hdev);
5799
5800 /* Check first if we already have the right
5801 * host state (host features set)
5802 */
5803 if (cp.le != lmp_host_le_capable(hdev) ||
5804 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005805 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5806 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005807 }
5808
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005809 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005810 /* Make sure the controller has a good default for
5811 * advertising data. This also applies to the case
5812 * where BR/EDR was toggled during the AUTO_OFF phase.
5813 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005814 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005815 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005816 update_scan_rsp_data(&req);
5817 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005818
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005819 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5820 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005821 }
5822
Johan Hedberg70da6242013-03-15 17:06:51 -05005823 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5824 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005825 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5826 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005827
5828 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005829 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5830 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005831 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005832 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005833 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005834 }
5835
Johan Hedberg229ab392013-03-15 17:06:53 -05005836 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005837}
5838
Johan Hedberg744cf192011-11-08 20:40:14 +02005839int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005840{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005841 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005842 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5843 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005844 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005845
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005846 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5847 return 0;
5848
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005849 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005850 if (powered_update_hci(hdev) == 0)
5851 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005852
Johan Hedberg229ab392013-03-15 17:06:53 -05005853 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5854 &match);
5855 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005856 }
5857
Johan Hedberg229ab392013-03-15 17:06:53 -05005858 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5859 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5860
5861 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5862 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5863 zero_cod, sizeof(zero_cod), NULL);
5864
5865new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005866 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005867
5868 if (match.sk)
5869 sock_put(match.sk);
5870
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005871 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005872}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005873
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005874void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005875{
5876 struct pending_cmd *cmd;
5877 u8 status;
5878
5879 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5880 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005881 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005882
5883 if (err == -ERFKILL)
5884 status = MGMT_STATUS_RFKILLED;
5885 else
5886 status = MGMT_STATUS_FAILED;
5887
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005888 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005889
5890 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005891}
5892
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005893void mgmt_discoverable_timeout(struct hci_dev *hdev)
5894{
5895 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005896
5897 hci_dev_lock(hdev);
5898
5899 /* When discoverable timeout triggers, then just make sure
5900 * the limited discoverable flag is cleared. Even in the case
5901 * of a timeout triggered from general discoverable, it is
5902 * safe to unconditionally clear the flag.
5903 */
5904 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005905 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005906
5907 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005908 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5909 u8 scan = SCAN_PAGE;
5910 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5911 sizeof(scan), &scan);
5912 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005913 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005914 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005915 hci_req_run(&req, NULL);
5916
5917 hdev->discov_timeout = 0;
5918
Johan Hedberg9a43e252013-10-20 19:00:07 +03005919 new_settings(hdev, NULL);
5920
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005921 hci_dev_unlock(hdev);
5922}
5923
Marcel Holtmann86a75642013-10-15 06:33:54 -07005924void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005925{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005926 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005927
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005928 /* Nothing needed here if there's a pending command since that
5929 * commands request completion callback takes care of everything
5930 * necessary.
5931 */
5932 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005933 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005934
Johan Hedbergbd107992014-02-24 14:52:19 +02005935 /* Powering off may clear the scan mode - don't let that interfere */
5936 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5937 return;
5938
Johan Hedberg9a43e252013-10-20 19:00:07 +03005939 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005940 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005941 } else {
5942 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005943 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005944 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005945
Johan Hedberg9a43e252013-10-20 19:00:07 +03005946 if (changed) {
5947 struct hci_request req;
5948
5949 /* In case this change in discoverable was triggered by
5950 * a disabling of connectable there could be a need to
5951 * update the advertising flags.
5952 */
5953 hci_req_init(&req, hdev);
5954 update_adv_data(&req);
5955 hci_req_run(&req, NULL);
5956
Marcel Holtmann86a75642013-10-15 06:33:54 -07005957 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005958 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005959}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005960
Marcel Holtmanna3309162013-10-15 06:33:55 -07005961void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005962{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005963 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005964
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005965 /* Nothing needed here if there's a pending command since that
5966 * commands request completion callback takes care of everything
5967 * necessary.
5968 */
5969 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005970 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005971
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005972 /* Powering off may clear the scan mode - don't let that interfere */
5973 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5974 return;
5975
Marcel Holtmanna3309162013-10-15 06:33:55 -07005976 if (connectable)
5977 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5978 else
5979 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005980
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005981 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005982 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005983}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005984
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005985void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005986{
Johan Hedbergca69b792011-11-11 18:10:00 +02005987 u8 mgmt_err = mgmt_status(status);
5988
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005989 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005990 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005991 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005992
5993 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005994 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005995 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005996}
5997
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005998void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5999 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006000{
Johan Hedberg86742e12011-11-07 23:13:38 +02006001 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006002
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006003 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006004
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006005 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006006 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006007 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006008 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006009 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006010 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006011
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006012 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006013}
Johan Hedbergf7520542011-01-20 12:34:39 +02006014
Johan Hedbergd7b25452014-05-23 13:19:53 +03006015static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6016{
6017 if (ltk->authenticated)
6018 return MGMT_LTK_AUTHENTICATED;
6019
6020 return MGMT_LTK_UNAUTHENTICATED;
6021}
6022
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006023void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006024{
6025 struct mgmt_ev_new_long_term_key ev;
6026
6027 memset(&ev, 0, sizeof(ev));
6028
Marcel Holtmann5192d302014-02-19 17:11:58 -08006029 /* Devices using resolvable or non-resolvable random addresses
6030 * without providing an indentity resolving key don't require
6031 * to store long term keys. Their addresses will change the
6032 * next time around.
6033 *
6034 * Only when a remote device provides an identity address
6035 * make sure the long term key is stored. If the remote
6036 * identity is known, the long term keys are internally
6037 * mapped to the identity address. So allow static random
6038 * and public addresses here.
6039 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006040 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6041 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6042 ev.store_hint = 0x00;
6043 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006044 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006045
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006046 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006047 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006048 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006049 ev.key.enc_size = key->enc_size;
6050 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006051 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006052
Johan Hedberg2ceba532014-06-16 19:25:16 +03006053 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006054 ev.key.master = 1;
6055
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006056 memcpy(ev.key.val, key->val, sizeof(key->val));
6057
Marcel Holtmann083368f2013-10-15 14:26:29 -07006058 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006059}
6060
Johan Hedberg95fbac82014-02-19 15:18:31 +02006061void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6062{
6063 struct mgmt_ev_new_irk ev;
6064
6065 memset(&ev, 0, sizeof(ev));
6066
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006067 /* For identity resolving keys from devices that are already
6068 * using a public address or static random address, do not
6069 * ask for storing this key. The identity resolving key really
6070 * is only mandatory for devices using resovlable random
6071 * addresses.
6072 *
6073 * Storing all identity resolving keys has the downside that
6074 * they will be also loaded on next boot of they system. More
6075 * identity resolving keys, means more time during scanning is
6076 * needed to actually resolve these addresses.
6077 */
6078 if (bacmp(&irk->rpa, BDADDR_ANY))
6079 ev.store_hint = 0x01;
6080 else
6081 ev.store_hint = 0x00;
6082
Johan Hedberg95fbac82014-02-19 15:18:31 +02006083 bacpy(&ev.rpa, &irk->rpa);
6084 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6085 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6086 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6087
6088 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6089}
6090
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006091void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6092 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006093{
6094 struct mgmt_ev_new_csrk ev;
6095
6096 memset(&ev, 0, sizeof(ev));
6097
6098 /* Devices using resolvable or non-resolvable random addresses
6099 * without providing an indentity resolving key don't require
6100 * to store signature resolving keys. Their addresses will change
6101 * the next time around.
6102 *
6103 * Only when a remote device provides an identity address
6104 * make sure the signature resolving key is stored. So allow
6105 * static random and public addresses here.
6106 */
6107 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6108 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6109 ev.store_hint = 0x00;
6110 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006111 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006112
6113 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6114 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6115 ev.key.master = csrk->master;
6116 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6117
6118 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6119}
6120
Andre Guedesffb5a8272014-07-01 18:10:11 -03006121void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006122 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6123 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006124{
6125 struct mgmt_ev_new_conn_param ev;
6126
Johan Hedbergc103aea2014-07-02 17:37:34 +03006127 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6128 return;
6129
Andre Guedesffb5a8272014-07-01 18:10:11 -03006130 memset(&ev, 0, sizeof(ev));
6131 bacpy(&ev.addr.bdaddr, bdaddr);
6132 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006133 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006134 ev.min_interval = cpu_to_le16(min_interval);
6135 ev.max_interval = cpu_to_le16(max_interval);
6136 ev.latency = cpu_to_le16(latency);
6137 ev.timeout = cpu_to_le16(timeout);
6138
6139 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6140}
6141
Marcel Holtmann94933992013-10-15 10:26:39 -07006142static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6143 u8 data_len)
6144{
6145 eir[eir_len++] = sizeof(type) + data_len;
6146 eir[eir_len++] = type;
6147 memcpy(&eir[eir_len], data, data_len);
6148 eir_len += data_len;
6149
6150 return eir_len;
6151}
6152
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006153void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6154 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6155 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006156{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006157 char buf[512];
6158 struct mgmt_ev_device_connected *ev = (void *) buf;
6159 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006160
Johan Hedbergb644ba32012-01-17 21:48:47 +02006161 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006162 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006163
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006164 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006165
Johan Hedbergb644ba32012-01-17 21:48:47 +02006166 if (name_len > 0)
6167 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006168 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006169
6170 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006171 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006172 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006173
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006174 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006175
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006176 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6177 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006178}
6179
Johan Hedberg8962ee72011-01-20 12:40:27 +02006180static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6181{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006182 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006183 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006184 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006185
Johan Hedberg88c3df12012-02-09 14:27:38 +02006186 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6187 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006188
Johan Hedbergaee9b212012-02-18 15:07:59 +02006189 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006190 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006191
6192 *sk = cmd->sk;
6193 sock_hold(*sk);
6194
Johan Hedberga664b5b2011-02-19 12:06:02 -03006195 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006196}
6197
Johan Hedberg124f6e32012-02-09 13:50:12 +02006198static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006199{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006200 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006201 struct mgmt_cp_unpair_device *cp = cmd->param;
6202 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006203
6204 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006205 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6206 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006207
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006208 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6209
Johan Hedbergaee9b212012-02-18 15:07:59 +02006210 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006211
6212 mgmt_pending_remove(cmd);
6213}
6214
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006215void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006216 u8 link_type, u8 addr_type, u8 reason,
6217 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006218{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006219 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006220 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006221 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006222
Johan Hedberg8b064a32014-02-24 14:52:22 +02006223 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6224 if (power_off) {
6225 struct mgmt_mode *cp = power_off->param;
6226
6227 /* The connection is still in hci_conn_hash so test for 1
6228 * instead of 0 to know if this is the last one.
6229 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006230 if (!cp->val && hci_conn_count(hdev) == 1) {
6231 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006232 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006233 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006234 }
6235
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006236 if (!mgmt_connected)
6237 return;
6238
Andre Guedes57eb7762013-10-30 19:01:41 -03006239 if (link_type != ACL_LINK && link_type != LE_LINK)
6240 return;
6241
Johan Hedberg744cf192011-11-08 20:40:14 +02006242 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006243
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006244 bacpy(&ev.addr.bdaddr, bdaddr);
6245 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6246 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006247
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006248 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006249
6250 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006251 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006252
Johan Hedberg124f6e32012-02-09 13:50:12 +02006253 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006254 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006255}
6256
Marcel Holtmann78929242013-10-06 23:55:47 -07006257void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6258 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006259{
Andre Guedes3655bba2013-10-30 19:01:40 -03006260 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6261 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006262 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006263 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006264
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006265 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6266 hdev);
6267
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006268 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006269 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006270 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006271
Andre Guedes3655bba2013-10-30 19:01:40 -03006272 cp = cmd->param;
6273
6274 if (bacmp(bdaddr, &cp->addr.bdaddr))
6275 return;
6276
6277 if (cp->addr.type != bdaddr_type)
6278 return;
6279
Johan Hedberg88c3df12012-02-09 14:27:38 +02006280 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006281 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006282
Marcel Holtmann78929242013-10-06 23:55:47 -07006283 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6284 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006285
Johan Hedberga664b5b2011-02-19 12:06:02 -03006286 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006287}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006288
Marcel Holtmann445608d2013-10-06 23:55:48 -07006289void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6290 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006291{
6292 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006293 struct pending_cmd *power_off;
6294
6295 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6296 if (power_off) {
6297 struct mgmt_mode *cp = power_off->param;
6298
6299 /* The connection is still in hci_conn_hash so test for 1
6300 * instead of 0 to know if this is the last one.
6301 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006302 if (!cp->val && hci_conn_count(hdev) == 1) {
6303 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006304 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006305 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006306 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006307
Johan Hedberg4c659c32011-11-07 23:13:39 +02006308 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006309 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006310 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006311
Marcel Holtmann445608d2013-10-06 23:55:48 -07006312 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006313}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006314
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006315void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006316{
6317 struct mgmt_ev_pin_code_request ev;
6318
Johan Hedbergd8457692012-02-17 14:24:57 +02006319 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006320 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006321 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006322
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006323 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006324}
6325
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006326void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6327 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006328{
6329 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006330 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006331
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006332 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006333 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006334 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006335
Johan Hedbergd8457692012-02-17 14:24:57 +02006336 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006337 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006338
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006339 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6340 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006341
Johan Hedberga664b5b2011-02-19 12:06:02 -03006342 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006343}
6344
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006345void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6346 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006347{
6348 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006349 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006350
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006351 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006352 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006353 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006354
Johan Hedbergd8457692012-02-17 14:24:57 +02006355 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006356 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006357
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006358 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6359 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006360
Johan Hedberga664b5b2011-02-19 12:06:02 -03006361 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006362}
Johan Hedberga5c29682011-02-19 12:05:57 -03006363
Johan Hedberg744cf192011-11-08 20:40:14 +02006364int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006365 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006366 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006367{
6368 struct mgmt_ev_user_confirm_request ev;
6369
Johan Hedberg744cf192011-11-08 20:40:14 +02006370 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006371
Johan Hedberg272d90d2012-02-09 15:26:12 +02006372 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006373 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006374 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006375 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006376
Johan Hedberg744cf192011-11-08 20:40:14 +02006377 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006378 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006379}
6380
Johan Hedberg272d90d2012-02-09 15:26:12 +02006381int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006382 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006383{
6384 struct mgmt_ev_user_passkey_request ev;
6385
6386 BT_DBG("%s", hdev->name);
6387
Johan Hedberg272d90d2012-02-09 15:26:12 +02006388 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006389 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006390
6391 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006392 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006393}
6394
Brian Gix0df4c182011-11-16 13:53:13 -08006395static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006396 u8 link_type, u8 addr_type, u8 status,
6397 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006398{
6399 struct pending_cmd *cmd;
6400 struct mgmt_rp_user_confirm_reply rp;
6401 int err;
6402
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006403 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006404 if (!cmd)
6405 return -ENOENT;
6406
Johan Hedberg272d90d2012-02-09 15:26:12 +02006407 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006408 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006409 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006410 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006411
Johan Hedberga664b5b2011-02-19 12:06:02 -03006412 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006413
6414 return err;
6415}
6416
Johan Hedberg744cf192011-11-08 20:40:14 +02006417int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006418 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006419{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006420 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006421 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006422}
6423
Johan Hedberg272d90d2012-02-09 15:26:12 +02006424int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006425 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006426{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006427 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006428 status,
6429 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006430}
Johan Hedberg2a611692011-02-19 12:06:00 -03006431
Brian Gix604086b2011-11-23 08:28:33 -08006432int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006433 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006434{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006435 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006436 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006437}
6438
Johan Hedberg272d90d2012-02-09 15:26:12 +02006439int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006440 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006441{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006442 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006443 status,
6444 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006445}
6446
Johan Hedberg92a25252012-09-06 18:39:26 +03006447int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6448 u8 link_type, u8 addr_type, u32 passkey,
6449 u8 entered)
6450{
6451 struct mgmt_ev_passkey_notify ev;
6452
6453 BT_DBG("%s", hdev->name);
6454
6455 bacpy(&ev.addr.bdaddr, bdaddr);
6456 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6457 ev.passkey = __cpu_to_le32(passkey);
6458 ev.entered = entered;
6459
6460 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6461}
6462
Marcel Holtmanne5460992013-10-15 14:26:23 -07006463void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6464 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006465{
6466 struct mgmt_ev_auth_failed ev;
6467
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006468 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006469 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006470 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006471
Marcel Holtmanne5460992013-10-15 14:26:23 -07006472 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006473}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006474
Marcel Holtmann464996a2013-10-15 14:26:24 -07006475void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006476{
6477 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006478 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006479
6480 if (status) {
6481 u8 mgmt_err = mgmt_status(status);
6482 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006483 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006484 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006485 }
6486
Marcel Holtmann464996a2013-10-15 14:26:24 -07006487 if (test_bit(HCI_AUTH, &hdev->flags))
6488 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6489 &hdev->dev_flags);
6490 else
6491 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6492 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006493
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006494 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006495 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006496
Johan Hedberg47990ea2012-02-22 11:58:37 +02006497 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006498 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006499
6500 if (match.sk)
6501 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006502}
6503
Johan Hedberg890ea892013-03-15 17:06:52 -05006504static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006505{
Johan Hedberg890ea892013-03-15 17:06:52 -05006506 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006507 struct hci_cp_write_eir cp;
6508
Johan Hedberg976eb202012-10-24 21:12:01 +03006509 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006510 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006511
Johan Hedbergc80da272012-02-22 15:38:48 +02006512 memset(hdev->eir, 0, sizeof(hdev->eir));
6513
Johan Hedbergcacaf522012-02-21 00:52:42 +02006514 memset(&cp, 0, sizeof(cp));
6515
Johan Hedberg890ea892013-03-15 17:06:52 -05006516 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006517}
6518
Marcel Holtmann3e248562013-10-15 14:26:25 -07006519void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006520{
6521 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006522 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006523 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006524
6525 if (status) {
6526 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006527
6528 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006529 &hdev->dev_flags)) {
6530 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006531 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006532 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006533
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006534 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6535 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006536 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006537 }
6538
6539 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006540 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006541 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006542 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6543 if (!changed)
6544 changed = test_and_clear_bit(HCI_HS_ENABLED,
6545 &hdev->dev_flags);
6546 else
6547 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006548 }
6549
6550 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6551
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006552 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006553 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006554
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006555 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006556 sock_put(match.sk);
6557
Johan Hedberg890ea892013-03-15 17:06:52 -05006558 hci_req_init(&req, hdev);
6559
Johan Hedberg37699722014-06-24 14:00:27 +03006560 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6561 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6562 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6563 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006564 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006565 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006566 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006567 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006568
6569 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006570}
6571
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006572void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6573{
6574 struct cmd_lookup match = { NULL, hdev };
6575 bool changed = false;
6576
6577 if (status) {
6578 u8 mgmt_err = mgmt_status(status);
6579
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006580 if (enable) {
6581 if (test_and_clear_bit(HCI_SC_ENABLED,
6582 &hdev->dev_flags))
6583 new_settings(hdev, NULL);
6584 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6585 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006586
6587 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6588 cmd_status_rsp, &mgmt_err);
6589 return;
6590 }
6591
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006592 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006593 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006594 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006595 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006596 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6597 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006598
6599 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6600 settings_rsp, &match);
6601
6602 if (changed)
6603 new_settings(hdev, match.sk);
6604
6605 if (match.sk)
6606 sock_put(match.sk);
6607}
6608
Johan Hedberg92da6092013-03-15 17:06:55 -05006609static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006610{
6611 struct cmd_lookup *match = data;
6612
Johan Hedberg90e70452012-02-23 23:09:40 +02006613 if (match->sk == NULL) {
6614 match->sk = cmd->sk;
6615 sock_hold(match->sk);
6616 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006617}
6618
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006619void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6620 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006621{
Johan Hedberg90e70452012-02-23 23:09:40 +02006622 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006623
Johan Hedberg92da6092013-03-15 17:06:55 -05006624 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6625 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6626 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006627
6628 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006629 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6630 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006631
6632 if (match.sk)
6633 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006634}
6635
Marcel Holtmann7667da32013-10-15 14:26:27 -07006636void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006637{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006638 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006639 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006640
Johan Hedberg13928972013-03-15 17:07:00 -05006641 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006642 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006643
6644 memset(&ev, 0, sizeof(ev));
6645 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006646 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006647
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006648 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006649 if (!cmd) {
6650 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006651
Johan Hedberg13928972013-03-15 17:07:00 -05006652 /* If this is a HCI command related to powering on the
6653 * HCI dev don't send any mgmt signals.
6654 */
6655 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006656 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006657 }
6658
Marcel Holtmann7667da32013-10-15 14:26:27 -07006659 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6660 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006661}
Szymon Jancc35938b2011-03-22 13:12:21 +01006662
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006663void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6664 u8 *randomizer192, u8 *hash256,
6665 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006666{
6667 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006668
Johan Hedberg744cf192011-11-08 20:40:14 +02006669 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006670
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006671 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006672 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006673 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006674
6675 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006676 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6677 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006678 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006679 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6680 hash256 && randomizer256) {
6681 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006682
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006683 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6684 memcpy(rp.randomizer192, randomizer192,
6685 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006686
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006687 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6688 memcpy(rp.randomizer256, randomizer256,
6689 sizeof(rp.randomizer256));
6690
6691 cmd_complete(cmd->sk, hdev->id,
6692 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6693 &rp, sizeof(rp));
6694 } else {
6695 struct mgmt_rp_read_local_oob_data rp;
6696
6697 memcpy(rp.hash, hash192, sizeof(rp.hash));
6698 memcpy(rp.randomizer, randomizer192,
6699 sizeof(rp.randomizer));
6700
6701 cmd_complete(cmd->sk, hdev->id,
6702 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6703 &rp, sizeof(rp));
6704 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006705 }
6706
6707 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006708}
Johan Hedberge17acd42011-03-30 23:57:16 +03006709
Marcel Holtmann901801b2013-10-06 23:55:51 -07006710void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006711 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6712 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006713{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006714 char buf[512];
6715 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006716 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006717
Johan Hedberg75ce2082014-07-02 22:42:01 +03006718 /* Don't send events for a non-kernel initiated discovery. With
6719 * LE one exception is if we have pend_le_reports > 0 in which
6720 * case we're doing passive scanning and want these events.
6721 */
6722 if (!hci_discovery_active(hdev)) {
6723 if (link_type == ACL_LINK)
6724 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006725 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006726 return;
6727 }
Andre Guedes12602d02013-04-30 15:29:40 -03006728
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006729 /* Make sure that the buffer is big enough. The 5 extra bytes
6730 * are for the potential CoD field.
6731 */
6732 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006733 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006734
Johan Hedberg1dc06092012-01-15 21:01:23 +02006735 memset(buf, 0, sizeof(buf));
6736
Johan Hedberg841c5642014-07-07 12:45:54 +03006737 bacpy(&ev->addr.bdaddr, bdaddr);
6738 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02006739 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006740 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006741
Johan Hedberg1dc06092012-01-15 21:01:23 +02006742 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006743 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006744
Johan Hedberg1dc06092012-01-15 21:01:23 +02006745 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6746 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006747 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006748
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006749 if (scan_rsp_len > 0)
6750 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6751
6752 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6753 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006754
Marcel Holtmann901801b2013-10-06 23:55:51 -07006755 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006756}
Johan Hedberga88a9652011-03-30 13:18:12 +03006757
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006758void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6759 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006760{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006761 struct mgmt_ev_device_found *ev;
6762 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6763 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006764
Johan Hedbergb644ba32012-01-17 21:48:47 +02006765 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006766
Johan Hedbergb644ba32012-01-17 21:48:47 +02006767 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006768
Johan Hedbergb644ba32012-01-17 21:48:47 +02006769 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006770 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006771 ev->rssi = rssi;
6772
6773 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006774 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006775
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006776 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006777
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006778 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006779}
Johan Hedberg314b2382011-04-27 10:29:57 -04006780
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006781void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006782{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006783 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006784 struct pending_cmd *cmd;
6785
Andre Guedes343fb142011-11-22 17:14:19 -03006786 BT_DBG("%s discovering %u", hdev->name, discovering);
6787
Johan Hedberg164a6e72011-11-01 17:06:44 +02006788 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006789 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006790 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006791 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006792
6793 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006794 u8 type = hdev->discovery.type;
6795
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006796 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6797 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006798 mgmt_pending_remove(cmd);
6799 }
6800
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006801 memset(&ev, 0, sizeof(ev));
6802 ev.type = hdev->discovery.type;
6803 ev.discovering = discovering;
6804
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006805 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006806}
Antti Julku5e762442011-08-25 16:48:02 +03006807
Marcel Holtmann5976e602013-10-06 04:08:14 -07006808static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6809{
6810 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006811}
6812
6813void mgmt_reenable_advertising(struct hci_dev *hdev)
6814{
6815 struct hci_request req;
6816
Marcel Holtmann5976e602013-10-06 04:08:14 -07006817 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6818 return;
6819
6820 hci_req_init(&req, hdev);
6821 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03006822 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006823}