blob: 91bccef63f30315048d9692735ca7ca72903d417 [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,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020095};
96
97static const u16 mgmt_events[] = {
98 MGMT_EV_CONTROLLER_ERROR,
99 MGMT_EV_INDEX_ADDED,
100 MGMT_EV_INDEX_REMOVED,
101 MGMT_EV_NEW_SETTINGS,
102 MGMT_EV_CLASS_OF_DEV_CHANGED,
103 MGMT_EV_LOCAL_NAME_CHANGED,
104 MGMT_EV_NEW_LINK_KEY,
105 MGMT_EV_NEW_LONG_TERM_KEY,
106 MGMT_EV_DEVICE_CONNECTED,
107 MGMT_EV_DEVICE_DISCONNECTED,
108 MGMT_EV_CONNECT_FAILED,
109 MGMT_EV_PIN_CODE_REQUEST,
110 MGMT_EV_USER_CONFIRM_REQUEST,
111 MGMT_EV_USER_PASSKEY_REQUEST,
112 MGMT_EV_AUTH_FAILED,
113 MGMT_EV_DEVICE_FOUND,
114 MGMT_EV_DISCOVERING,
115 MGMT_EV_DEVICE_BLOCKED,
116 MGMT_EV_DEVICE_UNBLOCKED,
117 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300118 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800119 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700120 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200121 MGMT_EV_DEVICE_ADDED,
122 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300123 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200124 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200125 MGMT_EV_UNCONF_INDEX_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200126};
127
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800128#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200129
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200130#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
131 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300139 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140};
141
Johan Hedbergca69b792011-11-11 18:10:00 +0200142/* HCI to MGMT error code conversion table */
143static u8 mgmt_status_table[] = {
144 MGMT_STATUS_SUCCESS,
145 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
146 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
147 MGMT_STATUS_FAILED, /* Hardware Failure */
148 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
149 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200150 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200151 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
152 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
153 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
154 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
155 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
156 MGMT_STATUS_BUSY, /* Command Disallowed */
157 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
158 MGMT_STATUS_REJECTED, /* Rejected Security */
159 MGMT_STATUS_REJECTED, /* Rejected Personal */
160 MGMT_STATUS_TIMEOUT, /* Host Timeout */
161 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
162 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
163 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
164 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
165 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
166 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
167 MGMT_STATUS_BUSY, /* Repeated Attempts */
168 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
169 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
170 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
171 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
172 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
173 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
174 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
175 MGMT_STATUS_FAILED, /* Unspecified Error */
176 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
177 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
178 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
179 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
180 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
181 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
182 MGMT_STATUS_FAILED, /* Unit Link Key Used */
183 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
184 MGMT_STATUS_TIMEOUT, /* Instant Passed */
185 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
186 MGMT_STATUS_FAILED, /* Transaction Collision */
187 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
188 MGMT_STATUS_REJECTED, /* QoS Rejected */
189 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
190 MGMT_STATUS_REJECTED, /* Insufficient Security */
191 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
192 MGMT_STATUS_BUSY, /* Role Switch Pending */
193 MGMT_STATUS_FAILED, /* Slot Violation */
194 MGMT_STATUS_FAILED, /* Role Switch Failed */
195 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
196 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
197 MGMT_STATUS_BUSY, /* Host Busy Pairing */
198 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
199 MGMT_STATUS_BUSY, /* Controller Busy */
200 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
201 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
202 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
203 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
204 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
205};
206
207static u8 mgmt_status(u8 hci_status)
208{
209 if (hci_status < ARRAY_SIZE(mgmt_status_table))
210 return mgmt_status_table[hci_status];
211
212 return MGMT_STATUS_FAILED;
213}
214
Szymon Janc4e51eae2011-02-25 19:05:48 +0100215static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200216{
217 struct sk_buff *skb;
218 struct mgmt_hdr *hdr;
219 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300220 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200221
Szymon Janc34eb5252011-02-28 14:10:08 +0100222 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200223
Andre Guedes790eff42012-06-07 19:05:46 -0300224 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200225 if (!skb)
226 return -ENOMEM;
227
228 hdr = (void *) skb_put(skb, sizeof(*hdr));
229
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700230 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100231 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200232 hdr->len = cpu_to_le16(sizeof(*ev));
233
234 ev = (void *) skb_put(skb, sizeof(*ev));
235 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200236 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200237
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300238 err = sock_queue_rcv_skb(sk, skb);
239 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200240 kfree_skb(skb);
241
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300242 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200243}
244
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200245static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300246 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200247{
248 struct sk_buff *skb;
249 struct mgmt_hdr *hdr;
250 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300251 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200252
253 BT_DBG("sock %p", sk);
254
Andre Guedes790eff42012-06-07 19:05:46 -0300255 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200256 if (!skb)
257 return -ENOMEM;
258
259 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200260
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700261 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100262 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200263 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200264
Johan Hedberga38528f2011-01-22 06:46:43 +0200265 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200266 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200267 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100268
269 if (rp)
270 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200271
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300272 err = sock_queue_rcv_skb(sk, skb);
273 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200274 kfree_skb(skb);
275
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100276 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200277}
278
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300279static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
280 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200281{
282 struct mgmt_rp_read_version rp;
283
284 BT_DBG("sock %p", sk);
285
286 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700287 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200288
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200289 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300290 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200291}
292
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300293static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
294 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200295{
296 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200297 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
298 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200299 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200300 size_t rp_size;
301 int i, err;
302
303 BT_DBG("sock %p", sk);
304
305 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
306
307 rp = kmalloc(rp_size, GFP_KERNEL);
308 if (!rp)
309 return -ENOMEM;
310
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700311 rp->num_commands = cpu_to_le16(num_commands);
312 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200313
314 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
315 put_unaligned_le16(mgmt_commands[i], opcode);
316
317 for (i = 0; i < num_events; i++, opcode++)
318 put_unaligned_le16(mgmt_events[i], opcode);
319
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200320 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300321 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200322 kfree(rp);
323
324 return err;
325}
326
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300327static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
328 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200329{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200330 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200331 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200332 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200333 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300334 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200335
336 BT_DBG("sock %p", sk);
337
338 read_lock(&hci_dev_list_lock);
339
340 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300341 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200342 if (d->dev_type == HCI_BREDR &&
343 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700344 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345 }
346
Johan Hedberga38528f2011-01-22 06:46:43 +0200347 rp_len = sizeof(*rp) + (2 * count);
348 rp = kmalloc(rp_len, GFP_ATOMIC);
349 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100350 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200351 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100352 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200353
Johan Hedberg476e44c2012-10-19 20:10:46 +0300354 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200355 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200356 if (test_bit(HCI_SETUP, &d->dev_flags) ||
357 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200358 continue;
359
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200360 /* Devices marked as raw-only are neither configured
361 * nor unconfigured controllers.
362 */
363 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700364 continue;
365
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200366 if (d->dev_type == HCI_BREDR &&
367 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700368 rp->index[count++] = cpu_to_le16(d->id);
369 BT_DBG("Added hci%u", d->id);
370 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200371 }
372
Johan Hedberg476e44c2012-10-19 20:10:46 +0300373 rp->num_controllers = cpu_to_le16(count);
374 rp_len = sizeof(*rp) + (2 * count);
375
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200376 read_unlock(&hci_dev_list_lock);
377
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200378 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300379 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200380
Johan Hedberga38528f2011-01-22 06:46:43 +0200381 kfree(rp);
382
383 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200384}
385
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200386static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
387 void *data, u16 data_len)
388{
389 struct mgmt_rp_read_unconf_index_list *rp;
390 struct hci_dev *d;
391 size_t rp_len;
392 u16 count;
393 int err;
394
395 BT_DBG("sock %p", sk);
396
397 read_lock(&hci_dev_list_lock);
398
399 count = 0;
400 list_for_each_entry(d, &hci_dev_list, list) {
401 if (d->dev_type == HCI_BREDR &&
402 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
403 count++;
404 }
405
406 rp_len = sizeof(*rp) + (2 * count);
407 rp = kmalloc(rp_len, GFP_ATOMIC);
408 if (!rp) {
409 read_unlock(&hci_dev_list_lock);
410 return -ENOMEM;
411 }
412
413 count = 0;
414 list_for_each_entry(d, &hci_dev_list, list) {
415 if (test_bit(HCI_SETUP, &d->dev_flags) ||
416 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
417 continue;
418
419 /* Devices marked as raw-only are neither configured
420 * nor unconfigured controllers.
421 */
422 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
423 continue;
424
425 if (d->dev_type == HCI_BREDR &&
426 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
427 rp->index[count++] = cpu_to_le16(d->id);
428 BT_DBG("Added hci%u", d->id);
429 }
430 }
431
432 rp->num_controllers = cpu_to_le16(count);
433 rp_len = sizeof(*rp) + (2 * count);
434
435 read_unlock(&hci_dev_list_lock);
436
437 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
438 0, rp, rp_len);
439
440 kfree(rp);
441
442 return err;
443}
444
Marcel Holtmanndbece372014-07-04 18:11:55 +0200445static bool is_configured(struct hci_dev *hdev)
446{
447 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
448 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
449 return false;
450
451 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
452 !bacmp(&hdev->public_addr, BDADDR_ANY))
453 return false;
454
455 return true;
456}
457
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200458static __le32 get_missing_options(struct hci_dev *hdev)
459{
460 u32 options = 0;
461
Marcel Holtmanndbece372014-07-04 18:11:55 +0200462 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
463 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200464 options |= MGMT_OPTION_EXTERNAL_CONFIG;
465
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200466 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
467 !bacmp(&hdev->public_addr, BDADDR_ANY))
468 options |= MGMT_OPTION_PUBLIC_ADDRESS;
469
470 return cpu_to_le32(options);
471}
472
Marcel Holtmanndbece372014-07-04 18:11:55 +0200473static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
474{
475 __le32 options = get_missing_options(hdev);
476
477 return cmd_complete(sk, hdev->id, opcode, 0, &options,
478 sizeof(options));
479}
480
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200481static int read_config_info(struct sock *sk, struct hci_dev *hdev,
482 void *data, u16 data_len)
483{
484 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200485 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200486
487 BT_DBG("sock %p %s", sk, hdev->name);
488
489 hci_dev_lock(hdev);
490
491 memset(&rp, 0, sizeof(rp));
492 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200493
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200494 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
495 options |= MGMT_OPTION_EXTERNAL_CONFIG;
496
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200497 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200498 options |= MGMT_OPTION_PUBLIC_ADDRESS;
499
500 rp.supported_options = cpu_to_le32(options);
501 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200502
503 hci_dev_unlock(hdev);
504
505 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
506 sizeof(rp));
507}
508
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200509static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200510{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200511 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200512
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200513 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200514 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800515 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200516
Andre Guedesed3fa312012-07-24 15:03:46 -0300517 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300518 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500519 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
520 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300521 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200522 settings |= MGMT_SETTING_BREDR;
523 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700524
525 if (lmp_ssp_capable(hdev)) {
526 settings |= MGMT_SETTING_SSP;
527 settings |= MGMT_SETTING_HS;
528 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800529
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800530 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200531 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800532 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700533 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100534
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300535 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200536 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300537 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200538 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300539 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200540
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200541 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
542 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200543 settings |= MGMT_SETTING_CONFIGURATION;
544
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200545 return settings;
546}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200547
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200548static u32 get_current_settings(struct hci_dev *hdev)
549{
550 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200551
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200552 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100553 settings |= MGMT_SETTING_POWERED;
554
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200555 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_CONNECTABLE;
557
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500558 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
559 settings |= MGMT_SETTING_FAST_CONNECTABLE;
560
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200561 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200562 settings |= MGMT_SETTING_DISCOVERABLE;
563
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200564 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200565 settings |= MGMT_SETTING_PAIRABLE;
566
Johan Hedberg56f87902013-10-02 13:43:13 +0300567 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200568 settings |= MGMT_SETTING_BREDR;
569
Johan Hedberg06199cf2012-02-22 16:37:11 +0200570 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200571 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200572
Johan Hedberg47990ea2012-02-22 11:58:37 +0200573 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200574 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200575
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200576 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200577 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200578
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200579 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
580 settings |= MGMT_SETTING_HS;
581
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200582 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300583 settings |= MGMT_SETTING_ADVERTISING;
584
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800585 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
586 settings |= MGMT_SETTING_SECURE_CONN;
587
Johan Hedberg0663b292014-06-24 13:15:50 +0300588 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800589 settings |= MGMT_SETTING_DEBUG_KEYS;
590
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200591 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
592 settings |= MGMT_SETTING_PRIVACY;
593
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200594 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200595}
596
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300597#define PNP_INFO_SVCLASS_ID 0x1200
598
Johan Hedberg213202e2013-01-27 00:31:33 +0200599static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
600{
601 u8 *ptr = data, *uuids_start = NULL;
602 struct bt_uuid *uuid;
603
604 if (len < 4)
605 return ptr;
606
607 list_for_each_entry(uuid, &hdev->uuids, list) {
608 u16 uuid16;
609
610 if (uuid->size != 16)
611 continue;
612
613 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
614 if (uuid16 < 0x1100)
615 continue;
616
617 if (uuid16 == PNP_INFO_SVCLASS_ID)
618 continue;
619
620 if (!uuids_start) {
621 uuids_start = ptr;
622 uuids_start[0] = 1;
623 uuids_start[1] = EIR_UUID16_ALL;
624 ptr += 2;
625 }
626
627 /* Stop if not enough space to put next UUID */
628 if ((ptr - data) + sizeof(u16) > len) {
629 uuids_start[1] = EIR_UUID16_SOME;
630 break;
631 }
632
633 *ptr++ = (uuid16 & 0x00ff);
634 *ptr++ = (uuid16 & 0xff00) >> 8;
635 uuids_start[0] += sizeof(uuid16);
636 }
637
638 return ptr;
639}
640
Johan Hedbergcdf19632013-01-27 00:31:34 +0200641static u8 *create_uuid32_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 < 6)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 if (uuid->size != 32)
651 continue;
652
653 if (!uuids_start) {
654 uuids_start = ptr;
655 uuids_start[0] = 1;
656 uuids_start[1] = EIR_UUID32_ALL;
657 ptr += 2;
658 }
659
660 /* Stop if not enough space to put next UUID */
661 if ((ptr - data) + sizeof(u32) > len) {
662 uuids_start[1] = EIR_UUID32_SOME;
663 break;
664 }
665
666 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
667 ptr += sizeof(u32);
668 uuids_start[0] += sizeof(u32);
669 }
670
671 return ptr;
672}
673
Johan Hedbergc00d5752013-01-27 00:31:35 +0200674static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
675{
676 u8 *ptr = data, *uuids_start = NULL;
677 struct bt_uuid *uuid;
678
679 if (len < 18)
680 return ptr;
681
682 list_for_each_entry(uuid, &hdev->uuids, list) {
683 if (uuid->size != 128)
684 continue;
685
686 if (!uuids_start) {
687 uuids_start = ptr;
688 uuids_start[0] = 1;
689 uuids_start[1] = EIR_UUID128_ALL;
690 ptr += 2;
691 }
692
693 /* Stop if not enough space to put next UUID */
694 if ((ptr - data) + 16 > len) {
695 uuids_start[1] = EIR_UUID128_SOME;
696 break;
697 }
698
699 memcpy(ptr, uuid->uuid, 16);
700 ptr += 16;
701 uuids_start[0] += 16;
702 }
703
704 return ptr;
705}
706
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300707static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
708{
709 struct pending_cmd *cmd;
710
711 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
712 if (cmd->opcode == opcode)
713 return cmd;
714 }
715
716 return NULL;
717}
718
Johan Hedberg95868422014-06-28 17:54:07 +0300719static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
720 struct hci_dev *hdev,
721 const void *data)
722{
723 struct pending_cmd *cmd;
724
725 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
726 if (cmd->user_data != data)
727 continue;
728 if (cmd->opcode == opcode)
729 return cmd;
730 }
731
732 return NULL;
733}
734
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700735static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
736{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700737 u8 ad_len = 0;
738 size_t name_len;
739
740 name_len = strlen(hdev->dev_name);
741 if (name_len > 0) {
742 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
743
744 if (name_len > max_len) {
745 name_len = max_len;
746 ptr[1] = EIR_NAME_SHORT;
747 } else
748 ptr[1] = EIR_NAME_COMPLETE;
749
750 ptr[0] = name_len + 1;
751
752 memcpy(ptr + 2, hdev->dev_name, name_len);
753
754 ad_len += (name_len + 2);
755 ptr += (name_len + 2);
756 }
757
758 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700759}
760
761static void update_scan_rsp_data(struct hci_request *req)
762{
763 struct hci_dev *hdev = req->hdev;
764 struct hci_cp_le_set_scan_rsp_data cp;
765 u8 len;
766
Johan Hedberg7751ef12013-10-19 23:38:15 +0300767 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700768 return;
769
770 memset(&cp, 0, sizeof(cp));
771
772 len = create_scan_rsp_data(hdev, cp.data);
773
Johan Hedbergeb438b52013-10-16 15:31:07 +0300774 if (hdev->scan_rsp_data_len == len &&
775 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700776 return;
777
Johan Hedbergeb438b52013-10-16 15:31:07 +0300778 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
779 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700780
781 cp.length = len;
782
783 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
784}
785
Johan Hedberg9a43e252013-10-20 19:00:07 +0300786static u8 get_adv_discov_flags(struct hci_dev *hdev)
787{
788 struct pending_cmd *cmd;
789
790 /* If there's a pending mgmt command the flags will not yet have
791 * their final values, so check for this first.
792 */
793 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
794 if (cmd) {
795 struct mgmt_mode *cp = cmd->param;
796 if (cp->val == 0x01)
797 return LE_AD_GENERAL;
798 else if (cp->val == 0x02)
799 return LE_AD_LIMITED;
800 } else {
801 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
802 return LE_AD_LIMITED;
803 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
804 return LE_AD_GENERAL;
805 }
806
807 return 0;
808}
809
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700810static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700811{
812 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700813
Johan Hedberg9a43e252013-10-20 19:00:07 +0300814 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700815
Johan Hedberge8340042014-01-30 11:16:50 -0800816 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700817 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700818
819 if (flags) {
820 BT_DBG("adv flags 0x%02x", flags);
821
822 ptr[0] = 2;
823 ptr[1] = EIR_FLAGS;
824 ptr[2] = flags;
825
826 ad_len += 3;
827 ptr += 3;
828 }
829
830 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
831 ptr[0] = 2;
832 ptr[1] = EIR_TX_POWER;
833 ptr[2] = (u8) hdev->adv_tx_power;
834
835 ad_len += 3;
836 ptr += 3;
837 }
838
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700839 return ad_len;
840}
841
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700842static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700843{
844 struct hci_dev *hdev = req->hdev;
845 struct hci_cp_le_set_adv_data cp;
846 u8 len;
847
Johan Hedberg10994ce2013-10-19 23:38:16 +0300848 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700849 return;
850
851 memset(&cp, 0, sizeof(cp));
852
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700853 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854
855 if (hdev->adv_data_len == len &&
856 memcmp(cp.data, hdev->adv_data, len) == 0)
857 return;
858
859 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
860 hdev->adv_data_len = len;
861
862 cp.length = len;
863
864 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
865}
866
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300867static void create_eir(struct hci_dev *hdev, u8 *data)
868{
869 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300870 size_t name_len;
871
872 name_len = strlen(hdev->dev_name);
873
874 if (name_len > 0) {
875 /* EIR Data type */
876 if (name_len > 48) {
877 name_len = 48;
878 ptr[1] = EIR_NAME_SHORT;
879 } else
880 ptr[1] = EIR_NAME_COMPLETE;
881
882 /* EIR Data length */
883 ptr[0] = name_len + 1;
884
885 memcpy(ptr + 2, hdev->dev_name, name_len);
886
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300887 ptr += (name_len + 2);
888 }
889
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100890 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700891 ptr[0] = 2;
892 ptr[1] = EIR_TX_POWER;
893 ptr[2] = (u8) hdev->inq_tx_power;
894
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700895 ptr += 3;
896 }
897
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700898 if (hdev->devid_source > 0) {
899 ptr[0] = 9;
900 ptr[1] = EIR_DEVICE_ID;
901
902 put_unaligned_le16(hdev->devid_source, ptr + 2);
903 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
904 put_unaligned_le16(hdev->devid_product, ptr + 6);
905 put_unaligned_le16(hdev->devid_version, ptr + 8);
906
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700907 ptr += 10;
908 }
909
Johan Hedberg213202e2013-01-27 00:31:33 +0200910 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200911 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200912 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300913}
914
Johan Hedberg890ea892013-03-15 17:06:52 -0500915static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300916{
Johan Hedberg890ea892013-03-15 17:06:52 -0500917 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300918 struct hci_cp_write_eir cp;
919
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200920 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500921 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200922
Johan Hedberg976eb202012-10-24 21:12:01 +0300923 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500924 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300925
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200926 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500927 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300928
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200929 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500930 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300931
932 memset(&cp, 0, sizeof(cp));
933
934 create_eir(hdev, cp.data);
935
936 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500937 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300938
939 memcpy(hdev->eir, cp.data, sizeof(cp.data));
940
Johan Hedberg890ea892013-03-15 17:06:52 -0500941 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300942}
943
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200944static u8 get_service_classes(struct hci_dev *hdev)
945{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300946 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200947 u8 val = 0;
948
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300949 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200950 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200951
952 return val;
953}
954
Johan Hedberg890ea892013-03-15 17:06:52 -0500955static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200956{
Johan Hedberg890ea892013-03-15 17:06:52 -0500957 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200958 u8 cod[3];
959
960 BT_DBG("%s", hdev->name);
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 Hedbergf87ea1d2013-10-19 23:38:17 +0300965 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
966 return;
967
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200968 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200970
971 cod[0] = hdev->minor_class;
972 cod[1] = hdev->major_class;
973 cod[2] = get_service_classes(hdev);
974
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700975 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
976 cod[1] |= 0x20;
977
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200978 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200980
Johan Hedberg890ea892013-03-15 17:06:52 -0500981 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200982}
983
Johan Hedberga4858cb2014-02-25 19:56:31 +0200984static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200985{
986 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200987
988 /* If there's a pending mgmt command the flag will not yet have
989 * it's final value, so check for this first.
990 */
991 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
992 if (cmd) {
993 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200994 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200995 }
996
Johan Hedberga4858cb2014-02-25 19:56:31 +0200997 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200998}
999
1000static void enable_advertising(struct hci_request *req)
1001{
1002 struct hci_dev *hdev = req->hdev;
1003 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001004 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001005 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001006
Johan Hedberg8d972502014-02-28 12:54:14 +02001007 /* Clear the HCI_ADVERTISING bit temporarily so that the
1008 * hci_update_random_address knows that it's safe to go ahead
1009 * and write a new random address. The flag will be set back on
1010 * as soon as the SET_ADV_ENABLE HCI command completes.
1011 */
1012 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1013
Johan Hedberga4858cb2014-02-25 19:56:31 +02001014 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001015
Johan Hedberga4858cb2014-02-25 19:56:31 +02001016 /* Set require_privacy to true only when non-connectable
1017 * advertising is used. In that case it is fine to use a
1018 * non-resolvable private address.
1019 */
1020 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001021 return;
1022
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001023 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001024 cp.min_interval = cpu_to_le16(0x0800);
1025 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001026 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001027 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001028 cp.channel_map = hdev->le_adv_channel_map;
1029
1030 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1031
1032 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1033}
1034
1035static void disable_advertising(struct hci_request *req)
1036{
1037 u8 enable = 0x00;
1038
1039 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1040}
1041
Johan Hedberg7d785252011-12-15 00:47:39 +02001042static void service_cache_off(struct work_struct *work)
1043{
1044 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001045 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001046 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001047
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001048 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001049 return;
1050
Johan Hedberg890ea892013-03-15 17:06:52 -05001051 hci_req_init(&req, hdev);
1052
Johan Hedberg7d785252011-12-15 00:47:39 +02001053 hci_dev_lock(hdev);
1054
Johan Hedberg890ea892013-03-15 17:06:52 -05001055 update_eir(&req);
1056 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001057
1058 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001059
1060 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001061}
1062
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001063static void rpa_expired(struct work_struct *work)
1064{
1065 struct hci_dev *hdev = container_of(work, struct hci_dev,
1066 rpa_expired.work);
1067 struct hci_request req;
1068
1069 BT_DBG("");
1070
1071 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1072
1073 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
1074 hci_conn_num(hdev, LE_LINK) > 0)
1075 return;
1076
1077 /* The generation of a new RPA and programming it into the
1078 * controller happens in the enable_advertising() function.
1079 */
1080
1081 hci_req_init(&req, hdev);
1082
1083 disable_advertising(&req);
1084 enable_advertising(&req);
1085
1086 hci_req_run(&req, NULL);
1087}
1088
Johan Hedberg6a919082012-02-28 06:17:26 +02001089static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001090{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001091 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001092 return;
1093
Johan Hedberg4f87da82012-03-02 19:55:56 +02001094 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001095 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001096
Johan Hedberg4f87da82012-03-02 19:55:56 +02001097 /* Non-mgmt controlled devices get this bit set
1098 * implicitly so that pairing works for them, however
1099 * for mgmt we require user-space to explicitly enable
1100 * it
1101 */
1102 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001103}
1104
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001105static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001106 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001107{
1108 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001109
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001110 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001111
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001112 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001113
Johan Hedberg03811012010-12-08 00:21:06 +02001114 memset(&rp, 0, sizeof(rp));
1115
Johan Hedberg03811012010-12-08 00:21:06 +02001116 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001117
1118 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001119 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001120
1121 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1122 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1123
1124 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001125
1126 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001127 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001128
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001129 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001130
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001131 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001132 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001133}
1134
1135static void mgmt_pending_free(struct pending_cmd *cmd)
1136{
1137 sock_put(cmd->sk);
1138 kfree(cmd->param);
1139 kfree(cmd);
1140}
1141
1142static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001143 struct hci_dev *hdev, void *data,
1144 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001145{
1146 struct pending_cmd *cmd;
1147
Johan Hedbergfca20012014-06-28 17:54:05 +03001148 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001149 if (!cmd)
1150 return NULL;
1151
1152 cmd->opcode = opcode;
1153 cmd->index = hdev->id;
1154
Andre Guedes12b94562012-06-07 19:05:45 -03001155 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001156 if (!cmd->param) {
1157 kfree(cmd);
1158 return NULL;
1159 }
1160
1161 if (data)
1162 memcpy(cmd->param, data, len);
1163
1164 cmd->sk = sk;
1165 sock_hold(sk);
1166
1167 list_add(&cmd->list, &hdev->mgmt_pending);
1168
1169 return cmd;
1170}
1171
1172static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001173 void (*cb)(struct pending_cmd *cmd,
1174 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001175 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001176{
Andre Guedesa3d09352013-02-01 11:21:30 -03001177 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001178
Andre Guedesa3d09352013-02-01 11:21:30 -03001179 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001180 if (opcode > 0 && cmd->opcode != opcode)
1181 continue;
1182
1183 cb(cmd, data);
1184 }
1185}
1186
Johan Hedberg03811012010-12-08 00:21:06 +02001187static void mgmt_pending_remove(struct pending_cmd *cmd)
1188{
1189 list_del(&cmd->list);
1190 mgmt_pending_free(cmd);
1191}
1192
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001193static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001194{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001195 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001196
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001197 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001198 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001199}
1200
Johan Hedberg8b064a32014-02-24 14:52:22 +02001201static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1202{
1203 BT_DBG("%s status 0x%02x", hdev->name, status);
1204
Johan Hedberga3172b72014-02-28 09:33:44 +02001205 if (hci_conn_count(hdev) == 0) {
1206 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001207 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001208 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001209}
1210
Johan Hedberg21a60d32014-06-10 14:05:58 +03001211static void hci_stop_discovery(struct hci_request *req)
1212{
1213 struct hci_dev *hdev = req->hdev;
1214 struct hci_cp_remote_name_req_cancel cp;
1215 struct inquiry_entry *e;
1216
1217 switch (hdev->discovery.state) {
1218 case DISCOVERY_FINDING:
1219 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1220 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1221 } else {
1222 cancel_delayed_work(&hdev->le_scan_disable);
1223 hci_req_add_le_scan_disable(req);
1224 }
1225
1226 break;
1227
1228 case DISCOVERY_RESOLVING:
1229 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1230 NAME_PENDING);
1231 if (!e)
1232 return;
1233
1234 bacpy(&cp.bdaddr, &e->data.bdaddr);
1235 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1236 &cp);
1237
1238 break;
1239
1240 default:
1241 /* Passive scanning */
1242 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1243 hci_req_add_le_scan_disable(req);
1244 break;
1245 }
1246}
1247
Johan Hedberg8b064a32014-02-24 14:52:22 +02001248static int clean_up_hci_state(struct hci_dev *hdev)
1249{
1250 struct hci_request req;
1251 struct hci_conn *conn;
1252
1253 hci_req_init(&req, hdev);
1254
1255 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1256 test_bit(HCI_PSCAN, &hdev->flags)) {
1257 u8 scan = 0x00;
1258 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1259 }
1260
1261 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1262 disable_advertising(&req);
1263
Johan Hedbergf8680f12014-06-10 14:05:59 +03001264 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001265
1266 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1267 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001268 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001269
Johan Hedbergc9910d02014-02-27 14:35:12 +02001270 switch (conn->state) {
1271 case BT_CONNECTED:
1272 case BT_CONFIG:
1273 dc.handle = cpu_to_le16(conn->handle);
1274 dc.reason = 0x15; /* Terminated due to Power Off */
1275 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1276 break;
1277 case BT_CONNECT:
1278 if (conn->type == LE_LINK)
1279 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1280 0, NULL);
1281 else if (conn->type == ACL_LINK)
1282 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1283 6, &conn->dst);
1284 break;
1285 case BT_CONNECT2:
1286 bacpy(&rej.bdaddr, &conn->dst);
1287 rej.reason = 0x15; /* Terminated due to Power Off */
1288 if (conn->type == ACL_LINK)
1289 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1290 sizeof(rej), &rej);
1291 else if (conn->type == SCO_LINK)
1292 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1293 sizeof(rej), &rej);
1294 break;
1295 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001296 }
1297
1298 return hci_req_run(&req, clean_up_hci_complete);
1299}
1300
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001301static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001302 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001303{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001304 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001305 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001306 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001307
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001308 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001309
Johan Hedberga7e80f22013-01-09 16:05:19 +02001310 if (cp->val != 0x00 && cp->val != 0x01)
1311 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1312 MGMT_STATUS_INVALID_PARAMS);
1313
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001314 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001315
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001316 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1317 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1318 MGMT_STATUS_BUSY);
1319 goto failed;
1320 }
1321
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001322 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1323 cancel_delayed_work(&hdev->power_off);
1324
1325 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001326 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1327 data, len);
1328 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001329 goto failed;
1330 }
1331 }
1332
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001333 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001334 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001335 goto failed;
1336 }
1337
Johan Hedberg03811012010-12-08 00:21:06 +02001338 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1339 if (!cmd) {
1340 err = -ENOMEM;
1341 goto failed;
1342 }
1343
Johan Hedberg8b064a32014-02-24 14:52:22 +02001344 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001345 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001346 err = 0;
1347 } else {
1348 /* Disconnect connections, stop scans, etc */
1349 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001350 if (!err)
1351 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1352 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001353
Johan Hedberg8b064a32014-02-24 14:52:22 +02001354 /* ENODATA means there were no HCI commands queued */
1355 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001356 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001357 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1358 err = 0;
1359 }
1360 }
Johan Hedberg03811012010-12-08 00:21:06 +02001361
1362failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001363 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001364 return err;
1365}
1366
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001367static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1368 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001369{
1370 struct sk_buff *skb;
1371 struct mgmt_hdr *hdr;
1372
Andre Guedes790eff42012-06-07 19:05:46 -03001373 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001374 if (!skb)
1375 return -ENOMEM;
1376
1377 hdr = (void *) skb_put(skb, sizeof(*hdr));
1378 hdr->opcode = cpu_to_le16(event);
1379 if (hdev)
1380 hdr->index = cpu_to_le16(hdev->id);
1381 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001382 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001383 hdr->len = cpu_to_le16(data_len);
1384
1385 if (data)
1386 memcpy(skb_put(skb, data_len), data, data_len);
1387
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001388 /* Time stamp */
1389 __net_timestamp(skb);
1390
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001391 hci_send_to_control(skb, skip_sk);
1392 kfree_skb(skb);
1393
1394 return 0;
1395}
1396
1397static int new_settings(struct hci_dev *hdev, struct sock *skip)
1398{
1399 __le32 ev;
1400
1401 ev = cpu_to_le32(get_current_settings(hdev));
1402
1403 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1404}
1405
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001406struct cmd_lookup {
1407 struct sock *sk;
1408 struct hci_dev *hdev;
1409 u8 mgmt_status;
1410};
1411
1412static void settings_rsp(struct pending_cmd *cmd, void *data)
1413{
1414 struct cmd_lookup *match = data;
1415
1416 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1417
1418 list_del(&cmd->list);
1419
1420 if (match->sk == NULL) {
1421 match->sk = cmd->sk;
1422 sock_hold(match->sk);
1423 }
1424
1425 mgmt_pending_free(cmd);
1426}
1427
1428static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1429{
1430 u8 *status = data;
1431
1432 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1433 mgmt_pending_remove(cmd);
1434}
1435
Johan Hedberge6fe7982013-10-02 15:45:22 +03001436static u8 mgmt_bredr_support(struct hci_dev *hdev)
1437{
1438 if (!lmp_bredr_capable(hdev))
1439 return MGMT_STATUS_NOT_SUPPORTED;
1440 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1441 return MGMT_STATUS_REJECTED;
1442 else
1443 return MGMT_STATUS_SUCCESS;
1444}
1445
1446static u8 mgmt_le_support(struct hci_dev *hdev)
1447{
1448 if (!lmp_le_capable(hdev))
1449 return MGMT_STATUS_NOT_SUPPORTED;
1450 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1451 return MGMT_STATUS_REJECTED;
1452 else
1453 return MGMT_STATUS_SUCCESS;
1454}
1455
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001456static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1457{
1458 struct pending_cmd *cmd;
1459 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001460 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001461 bool changed;
1462
1463 BT_DBG("status 0x%02x", status);
1464
1465 hci_dev_lock(hdev);
1466
1467 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1468 if (!cmd)
1469 goto unlock;
1470
1471 if (status) {
1472 u8 mgmt_err = mgmt_status(status);
1473 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001474 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001475 goto remove_cmd;
1476 }
1477
1478 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001479 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001480 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1481 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001482
1483 if (hdev->discov_timeout > 0) {
1484 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1485 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1486 to);
1487 }
1488 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001489 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1490 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001491 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001492
1493 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1494
1495 if (changed)
1496 new_settings(hdev, cmd->sk);
1497
Marcel Holtmann970ba522013-10-15 06:33:57 -07001498 /* When the discoverable mode gets changed, make sure
1499 * that class of device has the limited discoverable
1500 * bit correctly set.
1501 */
1502 hci_req_init(&req, hdev);
1503 update_class(&req);
1504 hci_req_run(&req, NULL);
1505
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001506remove_cmd:
1507 mgmt_pending_remove(cmd);
1508
1509unlock:
1510 hci_dev_unlock(hdev);
1511}
1512
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001513static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001514 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001515{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001516 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001517 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001518 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001519 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001520 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001521 int err;
1522
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001523 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001524
Johan Hedberg9a43e252013-10-20 19:00:07 +03001525 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1526 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001527 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001528 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001529
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001530 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001531 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1532 MGMT_STATUS_INVALID_PARAMS);
1533
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001534 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001535
1536 /* Disabling discoverable requires that no timeout is set,
1537 * and enabling limited discoverable requires a timeout.
1538 */
1539 if ((cp->val == 0x00 && timeout > 0) ||
1540 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001541 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001542 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001543
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001544 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001545
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001546 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001547 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001548 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001549 goto failed;
1550 }
1551
1552 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001553 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001554 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001555 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001556 goto failed;
1557 }
1558
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001559 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
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_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001562 goto failed;
1563 }
1564
1565 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001566 bool changed = false;
1567
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001568 /* Setting limited discoverable when powered off is
1569 * not a valid operation since it requires a timeout
1570 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1571 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001572 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1573 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1574 changed = true;
1575 }
1576
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001577 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001578 if (err < 0)
1579 goto failed;
1580
1581 if (changed)
1582 err = new_settings(hdev, sk);
1583
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001584 goto failed;
1585 }
1586
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001587 /* If the current mode is the same, then just update the timeout
1588 * value with the new value. And if only the timeout gets updated,
1589 * then no need for any HCI transactions.
1590 */
1591 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1592 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1593 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001594 cancel_delayed_work(&hdev->discov_off);
1595 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001596
Marcel Holtmann36261542013-10-15 08:28:51 -07001597 if (cp->val && hdev->discov_timeout > 0) {
1598 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001599 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001600 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001601 }
1602
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001603 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001604 goto failed;
1605 }
1606
1607 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1608 if (!cmd) {
1609 err = -ENOMEM;
1610 goto failed;
1611 }
1612
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001613 /* Cancel any potential discoverable timeout that might be
1614 * still active and store new timeout value. The arming of
1615 * the timeout happens in the complete handler.
1616 */
1617 cancel_delayed_work(&hdev->discov_off);
1618 hdev->discov_timeout = timeout;
1619
Johan Hedbergb456f872013-10-19 23:38:22 +03001620 /* Limited discoverable mode */
1621 if (cp->val == 0x02)
1622 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1623 else
1624 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1625
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001626 hci_req_init(&req, hdev);
1627
Johan Hedberg9a43e252013-10-20 19:00:07 +03001628 /* The procedure for LE-only controllers is much simpler - just
1629 * update the advertising data.
1630 */
1631 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1632 goto update_ad;
1633
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001634 scan = SCAN_PAGE;
1635
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001636 if (cp->val) {
1637 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001638
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001639 if (cp->val == 0x02) {
1640 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001641 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001642 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1643 hci_cp.iac_lap[1] = 0x8b;
1644 hci_cp.iac_lap[2] = 0x9e;
1645 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1646 hci_cp.iac_lap[4] = 0x8b;
1647 hci_cp.iac_lap[5] = 0x9e;
1648 } else {
1649 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001650 hci_cp.num_iac = 1;
1651 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1652 hci_cp.iac_lap[1] = 0x8b;
1653 hci_cp.iac_lap[2] = 0x9e;
1654 }
1655
1656 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1657 (hci_cp.num_iac * 3) + 1, &hci_cp);
1658
1659 scan |= SCAN_INQUIRY;
1660 } else {
1661 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1662 }
1663
1664 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001665
Johan Hedberg9a43e252013-10-20 19:00:07 +03001666update_ad:
1667 update_adv_data(&req);
1668
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001669 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001670 if (err < 0)
1671 mgmt_pending_remove(cmd);
1672
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001673failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001674 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001675 return err;
1676}
1677
Johan Hedberg406d7802013-03-15 17:07:09 -05001678static void write_fast_connectable(struct hci_request *req, bool enable)
1679{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001680 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001681 struct hci_cp_write_page_scan_activity acp;
1682 u8 type;
1683
Johan Hedberg547003b2013-10-21 16:51:53 +03001684 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1685 return;
1686
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001687 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1688 return;
1689
Johan Hedberg406d7802013-03-15 17:07:09 -05001690 if (enable) {
1691 type = PAGE_SCAN_TYPE_INTERLACED;
1692
1693 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001694 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001695 } else {
1696 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1697
1698 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001699 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001700 }
1701
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001702 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001703
Johan Hedbergbd98b992013-03-15 17:07:13 -05001704 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1705 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1706 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1707 sizeof(acp), &acp);
1708
1709 if (hdev->page_scan_type != type)
1710 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001711}
1712
Johan Hedberg2b76f452013-03-15 17:07:04 -05001713static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1714{
1715 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001716 struct mgmt_mode *cp;
1717 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001718
1719 BT_DBG("status 0x%02x", status);
1720
1721 hci_dev_lock(hdev);
1722
1723 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1724 if (!cmd)
1725 goto unlock;
1726
Johan Hedberg37438c12013-10-14 16:20:05 +03001727 if (status) {
1728 u8 mgmt_err = mgmt_status(status);
1729 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1730 goto remove_cmd;
1731 }
1732
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001733 cp = cmd->param;
1734 if (cp->val)
1735 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1736 else
1737 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1738
Johan Hedberg2b76f452013-03-15 17:07:04 -05001739 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1740
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001741 if (changed)
1742 new_settings(hdev, cmd->sk);
1743
Johan Hedberg37438c12013-10-14 16:20:05 +03001744remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001745 mgmt_pending_remove(cmd);
1746
1747unlock:
1748 hci_dev_unlock(hdev);
1749}
1750
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001751static int set_connectable_update_settings(struct hci_dev *hdev,
1752 struct sock *sk, u8 val)
1753{
1754 bool changed = false;
1755 int err;
1756
1757 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1758 changed = true;
1759
1760 if (val) {
1761 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1762 } else {
1763 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1764 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1765 }
1766
1767 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1768 if (err < 0)
1769 return err;
1770
1771 if (changed)
1772 return new_settings(hdev, sk);
1773
1774 return 0;
1775}
1776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001777static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001778 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001779{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001780 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001781 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001782 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001783 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001784 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001785
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001786 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001787
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001788 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1789 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001790 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001791 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001792
Johan Hedberga7e80f22013-01-09 16:05:19 +02001793 if (cp->val != 0x00 && cp->val != 0x01)
1794 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1795 MGMT_STATUS_INVALID_PARAMS);
1796
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001797 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001798
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001799 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001800 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001801 goto failed;
1802 }
1803
1804 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001805 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001806 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001807 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001808 goto failed;
1809 }
1810
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001811 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1812 if (!cmd) {
1813 err = -ENOMEM;
1814 goto failed;
1815 }
1816
Johan Hedberg2b76f452013-03-15 17:07:04 -05001817 hci_req_init(&req, hdev);
1818
Johan Hedberg9a43e252013-10-20 19:00:07 +03001819 /* If BR/EDR is not enabled and we disable advertising as a
1820 * by-product of disabling connectable, we need to update the
1821 * advertising flags.
1822 */
1823 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1824 if (!cp->val) {
1825 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1826 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1827 }
1828 update_adv_data(&req);
1829 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001830 if (cp->val) {
1831 scan = SCAN_PAGE;
1832 } else {
1833 scan = 0;
1834
1835 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001836 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001837 cancel_delayed_work(&hdev->discov_off);
1838 }
1839
1840 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1841 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001842
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001843 /* If we're going from non-connectable to connectable or
1844 * vice-versa when fast connectable is enabled ensure that fast
1845 * connectable gets disabled. write_fast_connectable won't do
1846 * anything if the page scan parameters are already what they
1847 * should be.
1848 */
1849 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001850 write_fast_connectable(&req, false);
1851
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001852 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1853 hci_conn_num(hdev, LE_LINK) == 0) {
1854 disable_advertising(&req);
1855 enable_advertising(&req);
1856 }
1857
Johan Hedberg2b76f452013-03-15 17:07:04 -05001858 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001859 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001860 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001861 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001862 err = set_connectable_update_settings(hdev, sk,
1863 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001864 goto failed;
1865 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001866
1867failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001868 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001869 return err;
1870}
1871
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001872static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001873 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001874{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001875 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001876 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001877 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001878
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001879 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001880
Johan Hedberga7e80f22013-01-09 16:05:19 +02001881 if (cp->val != 0x00 && cp->val != 0x01)
1882 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1883 MGMT_STATUS_INVALID_PARAMS);
1884
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001885 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001886
1887 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001888 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001890 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001891
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001892 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001893 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001894 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001895
Marcel Holtmann55594352013-10-06 16:11:57 -07001896 if (changed)
1897 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001898
Marcel Holtmann55594352013-10-06 16:11:57 -07001899unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001900 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001901 return err;
1902}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001903
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001904static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1905 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001906{
1907 struct mgmt_mode *cp = data;
1908 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001909 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001910 int err;
1911
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001912 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001913
Johan Hedberge6fe7982013-10-02 15:45:22 +03001914 status = mgmt_bredr_support(hdev);
1915 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001916 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001917 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001918
Johan Hedberga7e80f22013-01-09 16:05:19 +02001919 if (cp->val != 0x00 && cp->val != 0x01)
1920 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1921 MGMT_STATUS_INVALID_PARAMS);
1922
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001923 hci_dev_lock(hdev);
1924
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001925 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001926 bool changed = false;
1927
1928 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001929 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001930 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1931 changed = true;
1932 }
1933
1934 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1935 if (err < 0)
1936 goto failed;
1937
1938 if (changed)
1939 err = new_settings(hdev, sk);
1940
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001941 goto failed;
1942 }
1943
1944 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001945 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001946 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001947 goto failed;
1948 }
1949
1950 val = !!cp->val;
1951
1952 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1953 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1954 goto failed;
1955 }
1956
1957 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1958 if (!cmd) {
1959 err = -ENOMEM;
1960 goto failed;
1961 }
1962
1963 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1964 if (err < 0) {
1965 mgmt_pending_remove(cmd);
1966 goto failed;
1967 }
1968
1969failed:
1970 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001971 return err;
1972}
1973
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001974static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001975{
1976 struct mgmt_mode *cp = data;
1977 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001978 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001979 int err;
1980
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001981 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001982
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001983 status = mgmt_bredr_support(hdev);
1984 if (status)
1985 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1986
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001987 if (!lmp_ssp_capable(hdev))
1988 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1989 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001990
Johan Hedberga7e80f22013-01-09 16:05:19 +02001991 if (cp->val != 0x00 && cp->val != 0x01)
1992 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1993 MGMT_STATUS_INVALID_PARAMS);
1994
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001995 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001996
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001997 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001998 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001999
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002000 if (cp->val) {
2001 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2002 &hdev->dev_flags);
2003 } else {
2004 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2005 &hdev->dev_flags);
2006 if (!changed)
2007 changed = test_and_clear_bit(HCI_HS_ENABLED,
2008 &hdev->dev_flags);
2009 else
2010 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002011 }
2012
2013 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2014 if (err < 0)
2015 goto failed;
2016
2017 if (changed)
2018 err = new_settings(hdev, sk);
2019
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002020 goto failed;
2021 }
2022
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002023 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2024 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002025 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2026 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002027 goto failed;
2028 }
2029
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002030 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002031 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2032 goto failed;
2033 }
2034
2035 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2036 if (!cmd) {
2037 err = -ENOMEM;
2038 goto failed;
2039 }
2040
Johan Hedberg37699722014-06-24 14:00:27 +03002041 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2042 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2043 sizeof(cp->val), &cp->val);
2044
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002045 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002046 if (err < 0) {
2047 mgmt_pending_remove(cmd);
2048 goto failed;
2049 }
2050
2051failed:
2052 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002053 return err;
2054}
2055
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002056static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002057{
2058 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002059 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002060 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002061 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002062
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002063 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002064
Johan Hedberge6fe7982013-10-02 15:45:22 +03002065 status = mgmt_bredr_support(hdev);
2066 if (status)
2067 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002068
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002069 if (!lmp_ssp_capable(hdev))
2070 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2071 MGMT_STATUS_NOT_SUPPORTED);
2072
2073 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2074 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2075 MGMT_STATUS_REJECTED);
2076
Johan Hedberga7e80f22013-01-09 16:05:19 +02002077 if (cp->val != 0x00 && cp->val != 0x01)
2078 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2079 MGMT_STATUS_INVALID_PARAMS);
2080
Marcel Holtmannee392692013-10-01 22:59:23 -07002081 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002082
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002083 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002084 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002085 } else {
2086 if (hdev_is_powered(hdev)) {
2087 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2088 MGMT_STATUS_REJECTED);
2089 goto unlock;
2090 }
2091
Marcel Holtmannee392692013-10-01 22:59:23 -07002092 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002093 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002094
2095 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2096 if (err < 0)
2097 goto unlock;
2098
2099 if (changed)
2100 err = new_settings(hdev, sk);
2101
2102unlock:
2103 hci_dev_unlock(hdev);
2104 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002105}
2106
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002107static void le_enable_complete(struct hci_dev *hdev, u8 status)
2108{
2109 struct cmd_lookup match = { NULL, hdev };
2110
2111 if (status) {
2112 u8 mgmt_err = mgmt_status(status);
2113
2114 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2115 &mgmt_err);
2116 return;
2117 }
2118
2119 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2120
2121 new_settings(hdev, match.sk);
2122
2123 if (match.sk)
2124 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002125
2126 /* Make sure the controller has a good default for
2127 * advertising data. Restrict the update to when LE
2128 * has actually been enabled. During power on, the
2129 * update in powered_update_hci will take care of it.
2130 */
2131 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2132 struct hci_request req;
2133
2134 hci_dev_lock(hdev);
2135
2136 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002137 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002138 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002139 hci_req_run(&req, NULL);
2140
2141 hci_dev_unlock(hdev);
2142 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002143}
2144
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002145static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002146{
2147 struct mgmt_mode *cp = data;
2148 struct hci_cp_write_le_host_supported hci_cp;
2149 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002150 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002151 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002152 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002155
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002156 if (!lmp_le_capable(hdev))
2157 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2158 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002159
Johan Hedberga7e80f22013-01-09 16:05:19 +02002160 if (cp->val != 0x00 && cp->val != 0x01)
2161 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2162 MGMT_STATUS_INVALID_PARAMS);
2163
Johan Hedbergc73eee92013-04-19 18:35:21 +03002164 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002165 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002166 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2167 MGMT_STATUS_REJECTED);
2168
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002169 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002170
2171 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002172 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002173
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002174 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002175 bool changed = false;
2176
2177 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2178 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2179 changed = true;
2180 }
2181
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002182 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2183 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002184 changed = true;
2185 }
2186
Johan Hedberg06199cf2012-02-22 16:37:11 +02002187 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2188 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002189 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002190
2191 if (changed)
2192 err = new_settings(hdev, sk);
2193
Johan Hedberg1de028c2012-02-29 19:55:35 -08002194 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002195 }
2196
Johan Hedberg4375f102013-09-25 13:26:10 +03002197 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2198 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002199 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002200 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002201 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002202 }
2203
2204 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2205 if (!cmd) {
2206 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002207 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002208 }
2209
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002210 hci_req_init(&req, hdev);
2211
Johan Hedberg06199cf2012-02-22 16:37:11 +02002212 memset(&hci_cp, 0, sizeof(hci_cp));
2213
2214 if (val) {
2215 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002216 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002217 } else {
2218 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2219 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002220 }
2221
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002222 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2223 &hci_cp);
2224
2225 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302226 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002227 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002228
Johan Hedberg1de028c2012-02-29 19:55:35 -08002229unlock:
2230 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002231 return err;
2232}
2233
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002234/* This is a helper function to test for pending mgmt commands that can
2235 * cause CoD or EIR HCI commands. We can only allow one such pending
2236 * mgmt command at a time since otherwise we cannot easily track what
2237 * the current values are, will be, and based on that calculate if a new
2238 * HCI command needs to be sent and if yes with what value.
2239 */
2240static bool pending_eir_or_class(struct hci_dev *hdev)
2241{
2242 struct pending_cmd *cmd;
2243
2244 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2245 switch (cmd->opcode) {
2246 case MGMT_OP_ADD_UUID:
2247 case MGMT_OP_REMOVE_UUID:
2248 case MGMT_OP_SET_DEV_CLASS:
2249 case MGMT_OP_SET_POWERED:
2250 return true;
2251 }
2252 }
2253
2254 return false;
2255}
2256
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002257static const u8 bluetooth_base_uuid[] = {
2258 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2259 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2260};
2261
2262static u8 get_uuid_size(const u8 *uuid)
2263{
2264 u32 val;
2265
2266 if (memcmp(uuid, bluetooth_base_uuid, 12))
2267 return 128;
2268
2269 val = get_unaligned_le32(&uuid[12]);
2270 if (val > 0xffff)
2271 return 32;
2272
2273 return 16;
2274}
2275
Johan Hedberg92da6092013-03-15 17:06:55 -05002276static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2277{
2278 struct pending_cmd *cmd;
2279
2280 hci_dev_lock(hdev);
2281
2282 cmd = mgmt_pending_find(mgmt_op, hdev);
2283 if (!cmd)
2284 goto unlock;
2285
2286 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2287 hdev->dev_class, 3);
2288
2289 mgmt_pending_remove(cmd);
2290
2291unlock:
2292 hci_dev_unlock(hdev);
2293}
2294
2295static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2296{
2297 BT_DBG("status 0x%02x", status);
2298
2299 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2300}
2301
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002302static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002303{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002304 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002305 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002306 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002307 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002308 int err;
2309
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002310 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002311
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002312 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002313
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002314 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002315 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002316 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002317 goto failed;
2318 }
2319
Andre Guedes92c4c202012-06-07 19:05:44 -03002320 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002321 if (!uuid) {
2322 err = -ENOMEM;
2323 goto failed;
2324 }
2325
2326 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002327 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002328 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002329
Johan Hedbergde66aa62013-01-27 00:31:27 +02002330 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002331
Johan Hedberg890ea892013-03-15 17:06:52 -05002332 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002333
Johan Hedberg890ea892013-03-15 17:06:52 -05002334 update_class(&req);
2335 update_eir(&req);
2336
Johan Hedberg92da6092013-03-15 17:06:55 -05002337 err = hci_req_run(&req, add_uuid_complete);
2338 if (err < 0) {
2339 if (err != -ENODATA)
2340 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002341
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002342 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002343 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002344 goto failed;
2345 }
2346
2347 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002348 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002349 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002350 goto failed;
2351 }
2352
2353 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002354
2355failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002356 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002357 return err;
2358}
2359
Johan Hedberg24b78d02012-02-23 23:24:30 +02002360static bool enable_service_cache(struct hci_dev *hdev)
2361{
2362 if (!hdev_is_powered(hdev))
2363 return false;
2364
2365 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002366 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2367 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002368 return true;
2369 }
2370
2371 return false;
2372}
2373
Johan Hedberg92da6092013-03-15 17:06:55 -05002374static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2375{
2376 BT_DBG("status 0x%02x", status);
2377
2378 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2379}
2380
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002381static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002382 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002383{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002384 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002385 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002386 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002387 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 -05002388 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002389 int err, found;
2390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002391 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002392
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002393 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002394
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002395 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002397 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002398 goto unlock;
2399 }
2400
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002402 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002403
Johan Hedberg24b78d02012-02-23 23:24:30 +02002404 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002405 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002406 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002407 goto unlock;
2408 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002409
Johan Hedberg9246a862012-02-23 21:33:16 +02002410 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002411 }
2412
2413 found = 0;
2414
Johan Hedberg056341c2013-01-27 00:31:30 +02002415 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002416 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2417 continue;
2418
2419 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002420 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002421 found++;
2422 }
2423
2424 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002425 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002426 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002427 goto unlock;
2428 }
2429
Johan Hedberg9246a862012-02-23 21:33:16 +02002430update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002431 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002432
Johan Hedberg890ea892013-03-15 17:06:52 -05002433 update_class(&req);
2434 update_eir(&req);
2435
Johan Hedberg92da6092013-03-15 17:06:55 -05002436 err = hci_req_run(&req, remove_uuid_complete);
2437 if (err < 0) {
2438 if (err != -ENODATA)
2439 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002440
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002441 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002442 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002443 goto unlock;
2444 }
2445
2446 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002447 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002448 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002449 goto unlock;
2450 }
2451
2452 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002453
2454unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002455 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002456 return err;
2457}
2458
Johan Hedberg92da6092013-03-15 17:06:55 -05002459static void set_class_complete(struct hci_dev *hdev, u8 status)
2460{
2461 BT_DBG("status 0x%02x", status);
2462
2463 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2464}
2465
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002466static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002467 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002468{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002469 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002470 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002471 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002472 int err;
2473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002474 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002475
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002476 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002477 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2478 MGMT_STATUS_NOT_SUPPORTED);
2479
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002480 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002481
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002482 if (pending_eir_or_class(hdev)) {
2483 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2484 MGMT_STATUS_BUSY);
2485 goto unlock;
2486 }
2487
2488 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2489 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2490 MGMT_STATUS_INVALID_PARAMS);
2491 goto unlock;
2492 }
2493
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002494 hdev->major_class = cp->major;
2495 hdev->minor_class = cp->minor;
2496
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002497 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002498 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002499 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002500 goto unlock;
2501 }
2502
Johan Hedberg890ea892013-03-15 17:06:52 -05002503 hci_req_init(&req, hdev);
2504
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002505 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002506 hci_dev_unlock(hdev);
2507 cancel_delayed_work_sync(&hdev->service_cache);
2508 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002509 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002510 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002511
Johan Hedberg890ea892013-03-15 17:06:52 -05002512 update_class(&req);
2513
Johan Hedberg92da6092013-03-15 17:06:55 -05002514 err = hci_req_run(&req, set_class_complete);
2515 if (err < 0) {
2516 if (err != -ENODATA)
2517 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002518
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002519 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002520 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002521 goto unlock;
2522 }
2523
2524 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002525 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002526 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002527 goto unlock;
2528 }
2529
2530 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002531
Johan Hedbergb5235a62012-02-21 14:32:24 +02002532unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002533 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002534 return err;
2535}
2536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002537static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002538 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002539{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002540 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002541 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2542 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002543 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002544 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002545 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002546
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002547 BT_DBG("request for %s", hdev->name);
2548
2549 if (!lmp_bredr_capable(hdev))
2550 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2551 MGMT_STATUS_NOT_SUPPORTED);
2552
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002553 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002554 if (key_count > max_key_count) {
2555 BT_ERR("load_link_keys: too big key_count value %u",
2556 key_count);
2557 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2558 MGMT_STATUS_INVALID_PARAMS);
2559 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002560
Johan Hedberg86742e12011-11-07 23:13:38 +02002561 expected_len = sizeof(*cp) + key_count *
2562 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002563 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002564 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002565 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002566 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002567 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002568 }
2569
Johan Hedberg4ae14302013-01-20 14:27:13 +02002570 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2571 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2572 MGMT_STATUS_INVALID_PARAMS);
2573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002574 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002575 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002576
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002577 for (i = 0; i < key_count; i++) {
2578 struct mgmt_link_key_info *key = &cp->keys[i];
2579
Marcel Holtmann8e991132014-01-10 02:07:25 -08002580 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002581 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2582 MGMT_STATUS_INVALID_PARAMS);
2583 }
2584
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002585 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002586
2587 hci_link_keys_clear(hdev);
2588
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002589 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002590 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2591 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002592 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002593 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2594 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002595
2596 if (changed)
2597 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002598
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002599 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002600 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002601
Johan Hedberg58e92932014-06-24 14:00:26 +03002602 /* Always ignore debug keys and require a new pairing if
2603 * the user wants to use them.
2604 */
2605 if (key->type == HCI_LK_DEBUG_COMBINATION)
2606 continue;
2607
Johan Hedberg7652ff62014-06-24 13:15:49 +03002608 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2609 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002610 }
2611
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002612 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002613
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002614 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002615
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002616 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002617}
2618
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002619static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002620 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002621{
2622 struct mgmt_ev_device_unpaired ev;
2623
2624 bacpy(&ev.addr.bdaddr, bdaddr);
2625 ev.addr.type = addr_type;
2626
2627 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002628 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002629}
2630
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002631static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002632 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002633{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002634 struct mgmt_cp_unpair_device *cp = data;
2635 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002636 struct hci_cp_disconnect dc;
2637 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002638 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639 int err;
2640
Johan Hedberga8a1d192011-11-10 15:54:38 +02002641 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002642 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2643 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002644
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002645 if (!bdaddr_type_is_valid(cp->addr.type))
2646 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2647 MGMT_STATUS_INVALID_PARAMS,
2648 &rp, sizeof(rp));
2649
Johan Hedberg118da702013-01-20 14:27:20 +02002650 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2651 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2652 MGMT_STATUS_INVALID_PARAMS,
2653 &rp, sizeof(rp));
2654
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002655 hci_dev_lock(hdev);
2656
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002657 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002658 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002659 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002660 goto unlock;
2661 }
2662
Johan Hedberge0b2b272014-02-18 17:14:31 +02002663 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002664 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002665 } else {
2666 u8 addr_type;
2667
2668 if (cp->addr.type == BDADDR_LE_PUBLIC)
2669 addr_type = ADDR_LE_DEV_PUBLIC;
2670 else
2671 addr_type = ADDR_LE_DEV_RANDOM;
2672
Johan Hedberga7ec7332014-02-18 17:14:35 +02002673 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2674
Andre Guedesa9b0a042014-02-26 20:21:52 -03002675 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2676
Johan Hedberge0b2b272014-02-18 17:14:31 +02002677 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2678 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002679
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002680 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002681 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002682 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002683 goto unlock;
2684 }
2685
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002686 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002687 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002688 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002689 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002690 else
2691 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002692 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002693 } else {
2694 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002695 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002696
Johan Hedberga8a1d192011-11-10 15:54:38 +02002697 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002698 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002699 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002700 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002701 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702 }
2703
Johan Hedberg124f6e32012-02-09 13:50:12 +02002704 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002705 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002706 if (!cmd) {
2707 err = -ENOMEM;
2708 goto unlock;
2709 }
2710
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002711 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002712 dc.reason = 0x13; /* Remote User Terminated Connection */
2713 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2714 if (err < 0)
2715 mgmt_pending_remove(cmd);
2716
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002717unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002718 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002719 return err;
2720}
2721
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002722static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002723 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002724{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002725 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002726 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002727 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002728 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002729 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002730 int err;
2731
2732 BT_DBG("");
2733
Johan Hedberg06a63b12013-01-20 14:27:21 +02002734 memset(&rp, 0, sizeof(rp));
2735 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2736 rp.addr.type = cp->addr.type;
2737
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002738 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002739 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2740 MGMT_STATUS_INVALID_PARAMS,
2741 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002742
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002743 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002744
2745 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002746 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2747 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002748 goto failed;
2749 }
2750
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002751 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002752 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2753 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002754 goto failed;
2755 }
2756
Andre Guedes591f47f2012-04-24 21:02:49 -03002757 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002758 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2759 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002760 else
2761 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002762
Vishal Agarwalf9607272012-06-13 05:32:43 +05302763 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002764 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2765 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002766 goto failed;
2767 }
2768
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002769 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002770 if (!cmd) {
2771 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002772 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002773 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002774
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002775 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002776 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002777
2778 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2779 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002780 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002781
2782failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002783 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002784 return err;
2785}
2786
Andre Guedes57c14772012-04-24 21:02:50 -03002787static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002788{
2789 switch (link_type) {
2790 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002791 switch (addr_type) {
2792 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002793 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002794
Johan Hedberg48264f02011-11-09 13:58:58 +02002795 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002796 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002797 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002798 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002799
Johan Hedberg4c659c32011-11-07 23:13:39 +02002800 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002801 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002802 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002803 }
2804}
2805
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002806static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2807 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002808{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002809 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002810 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002811 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002812 int err;
2813 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002814
2815 BT_DBG("");
2816
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002817 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002818
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002819 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002820 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002821 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002822 goto unlock;
2823 }
2824
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002825 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002826 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2827 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002828 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002829 }
2830
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002831 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002832 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002833 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002834 err = -ENOMEM;
2835 goto unlock;
2836 }
2837
Johan Hedberg2784eb42011-01-21 13:56:35 +02002838 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002839 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002840 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2841 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002842 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002843 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002844 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002845 continue;
2846 i++;
2847 }
2848
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002849 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002850
Johan Hedberg4c659c32011-11-07 23:13:39 +02002851 /* Recalculate length in case of filtered SCO connections, etc */
2852 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002853
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002854 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002855 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002856
Johan Hedberga38528f2011-01-22 06:46:43 +02002857 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002858
2859unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002860 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002861 return err;
2862}
2863
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002864static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002865 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002866{
2867 struct pending_cmd *cmd;
2868 int err;
2869
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002870 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002871 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002872 if (!cmd)
2873 return -ENOMEM;
2874
Johan Hedbergd8457692012-02-17 14:24:57 +02002875 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002876 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002877 if (err < 0)
2878 mgmt_pending_remove(cmd);
2879
2880 return err;
2881}
2882
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002883static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002884 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002885{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002886 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002887 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002888 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002889 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002890 int err;
2891
2892 BT_DBG("");
2893
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002894 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002895
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002896 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002897 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002898 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002899 goto failed;
2900 }
2901
Johan Hedbergd8457692012-02-17 14:24:57 +02002902 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002903 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002904 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002905 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002906 goto failed;
2907 }
2908
2909 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002910 struct mgmt_cp_pin_code_neg_reply ncp;
2911
2912 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002913
2914 BT_ERR("PIN code is not 16 bytes long");
2915
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002916 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002917 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002918 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002919 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002920
2921 goto failed;
2922 }
2923
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002924 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002925 if (!cmd) {
2926 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002927 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002928 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002929
Johan Hedbergd8457692012-02-17 14:24:57 +02002930 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002931 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002932 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002933
2934 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2935 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002936 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002937
2938failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002939 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002940 return err;
2941}
2942
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002943static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2944 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002945{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002946 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002947
2948 BT_DBG("");
2949
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002950 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2951 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2952 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2953
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002954 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002955
2956 hdev->io_capability = cp->io_capability;
2957
2958 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002959 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002960
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002961 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002962
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002963 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2964 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002965}
2966
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002967static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002968{
2969 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002970 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002971
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002972 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002973 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2974 continue;
2975
Johan Hedberge9a416b2011-02-19 12:05:56 -03002976 if (cmd->user_data != conn)
2977 continue;
2978
2979 return cmd;
2980 }
2981
2982 return NULL;
2983}
2984
2985static void pairing_complete(struct pending_cmd *cmd, u8 status)
2986{
2987 struct mgmt_rp_pair_device rp;
2988 struct hci_conn *conn = cmd->user_data;
2989
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002990 bacpy(&rp.addr.bdaddr, &conn->dst);
2991 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002992
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002993 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002994 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002995
2996 /* So we don't get further callbacks for this connection */
2997 conn->connect_cfm_cb = NULL;
2998 conn->security_cfm_cb = NULL;
2999 conn->disconn_cfm_cb = NULL;
3000
David Herrmann76a68ba2013-04-06 20:28:37 +02003001 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003002
Johan Hedberga664b5b2011-02-19 12:06:02 -03003003 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004}
3005
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003006void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3007{
3008 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3009 struct pending_cmd *cmd;
3010
3011 cmd = find_pairing(conn);
3012 if (cmd)
3013 pairing_complete(cmd, status);
3014}
3015
Johan Hedberge9a416b2011-02-19 12:05:56 -03003016static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3017{
3018 struct pending_cmd *cmd;
3019
3020 BT_DBG("status %u", status);
3021
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003022 cmd = find_pairing(conn);
3023 if (!cmd)
3024 BT_DBG("Unable to find a pending command");
3025 else
Johan Hedberge2113262012-02-18 15:20:03 +02003026 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003027}
3028
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003029static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303030{
3031 struct pending_cmd *cmd;
3032
3033 BT_DBG("status %u", status);
3034
3035 if (!status)
3036 return;
3037
3038 cmd = find_pairing(conn);
3039 if (!cmd)
3040 BT_DBG("Unable to find a pending command");
3041 else
3042 pairing_complete(cmd, mgmt_status(status));
3043}
3044
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003045static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003046 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003047{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003048 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003049 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003050 struct pending_cmd *cmd;
3051 u8 sec_level, auth_type;
3052 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003053 int err;
3054
3055 BT_DBG("");
3056
Szymon Jancf950a30e2013-01-18 12:48:07 +01003057 memset(&rp, 0, sizeof(rp));
3058 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3059 rp.addr.type = cp->addr.type;
3060
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003061 if (!bdaddr_type_is_valid(cp->addr.type))
3062 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3063 MGMT_STATUS_INVALID_PARAMS,
3064 &rp, sizeof(rp));
3065
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003066 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3067 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3068 MGMT_STATUS_INVALID_PARAMS,
3069 &rp, sizeof(rp));
3070
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003071 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003072
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003073 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003074 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3075 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003076 goto unlock;
3077 }
3078
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003079 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003080 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003081
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003082 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003083 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3084 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003085 } else {
3086 u8 addr_type;
3087
3088 /* Convert from L2CAP channel address type to HCI address type
3089 */
3090 if (cp->addr.type == BDADDR_LE_PUBLIC)
3091 addr_type = ADDR_LE_DEV_PUBLIC;
3092 else
3093 addr_type = ADDR_LE_DEV_RANDOM;
3094
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003095 /* When pairing a new device, it is expected to remember
3096 * this device for future connections. Adding the connection
3097 * parameter information ahead of time allows tracking
3098 * of the slave preferred values and will speed up any
3099 * further connection establishment.
3100 *
3101 * If connection parameters already exist, then they
3102 * will be kept and this function does nothing.
3103 */
3104 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3105
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003106 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03003107 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003108 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003109
Ville Tervo30e76272011-02-22 16:10:53 -03003110 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003111 int status;
3112
3113 if (PTR_ERR(conn) == -EBUSY)
3114 status = MGMT_STATUS_BUSY;
3115 else
3116 status = MGMT_STATUS_CONNECT_FAILED;
3117
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003118 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003119 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003120 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003121 goto unlock;
3122 }
3123
3124 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003125 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003126 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003127 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003128 goto unlock;
3129 }
3130
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003131 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003132 if (!cmd) {
3133 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003134 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003135 goto unlock;
3136 }
3137
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003138 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003139 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003140 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003141 conn->security_cfm_cb = pairing_complete_cb;
3142 conn->disconn_cfm_cb = pairing_complete_cb;
3143 } else {
3144 conn->connect_cfm_cb = le_pairing_complete_cb;
3145 conn->security_cfm_cb = le_pairing_complete_cb;
3146 conn->disconn_cfm_cb = le_pairing_complete_cb;
3147 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003148
Johan Hedberge9a416b2011-02-19 12:05:56 -03003149 conn->io_capability = cp->io_cap;
3150 cmd->user_data = conn;
3151
3152 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003153 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003154 pairing_complete(cmd, 0);
3155
3156 err = 0;
3157
3158unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003159 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003160 return err;
3161}
3162
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003163static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3164 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003165{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003166 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003167 struct pending_cmd *cmd;
3168 struct hci_conn *conn;
3169 int err;
3170
3171 BT_DBG("");
3172
Johan Hedberg28424702012-02-02 04:02:29 +02003173 hci_dev_lock(hdev);
3174
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003175 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003176 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003177 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003178 goto unlock;
3179 }
3180
Johan Hedberg28424702012-02-02 04:02:29 +02003181 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3182 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003183 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003184 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003185 goto unlock;
3186 }
3187
3188 conn = cmd->user_data;
3189
3190 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003191 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003192 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003193 goto unlock;
3194 }
3195
3196 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003198 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003199 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003200unlock:
3201 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003202 return err;
3203}
3204
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003205static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003206 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003207 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003208{
Johan Hedberga5c29682011-02-19 12:05:57 -03003209 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003210 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003211 int err;
3212
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003213 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003214
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003215 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003216 err = cmd_complete(sk, hdev->id, mgmt_op,
3217 MGMT_STATUS_NOT_POWERED, addr,
3218 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003219 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003220 }
3221
Johan Hedberg1707c602013-03-15 17:07:15 -05003222 if (addr->type == BDADDR_BREDR)
3223 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003224 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003225 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003226
Johan Hedberg272d90d2012-02-09 15:26:12 +02003227 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003228 err = cmd_complete(sk, hdev->id, mgmt_op,
3229 MGMT_STATUS_NOT_CONNECTED, addr,
3230 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003231 goto done;
3232 }
3233
Johan Hedberg1707c602013-03-15 17:07:15 -05003234 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003235 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003236 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003237 err = cmd_complete(sk, hdev->id, mgmt_op,
3238 MGMT_STATUS_SUCCESS, addr,
3239 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003240 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003241 err = cmd_complete(sk, hdev->id, mgmt_op,
3242 MGMT_STATUS_FAILED, addr,
3243 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003244
Brian Gix47c15e22011-11-16 13:53:14 -08003245 goto done;
3246 }
3247
Johan Hedberg1707c602013-03-15 17:07:15 -05003248 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003249 if (!cmd) {
3250 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003251 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003252 }
3253
Brian Gix0df4c182011-11-16 13:53:13 -08003254 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003255 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3256 struct hci_cp_user_passkey_reply cp;
3257
Johan Hedberg1707c602013-03-15 17:07:15 -05003258 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003259 cp.passkey = passkey;
3260 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3261 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003262 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3263 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003264
Johan Hedberga664b5b2011-02-19 12:06:02 -03003265 if (err < 0)
3266 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003267
Brian Gix0df4c182011-11-16 13:53:13 -08003268done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003269 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003270 return err;
3271}
3272
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303273static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3274 void *data, u16 len)
3275{
3276 struct mgmt_cp_pin_code_neg_reply *cp = data;
3277
3278 BT_DBG("");
3279
Johan Hedberg1707c602013-03-15 17:07:15 -05003280 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303281 MGMT_OP_PIN_CODE_NEG_REPLY,
3282 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3283}
3284
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003285static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3286 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003287{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003288 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003289
3290 BT_DBG("");
3291
3292 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003293 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003294 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003295
Johan Hedberg1707c602013-03-15 17:07:15 -05003296 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003297 MGMT_OP_USER_CONFIRM_REPLY,
3298 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003299}
3300
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003301static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003302 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003303{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003304 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003305
3306 BT_DBG("");
3307
Johan Hedberg1707c602013-03-15 17:07:15 -05003308 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003309 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3310 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003311}
3312
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003313static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3314 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003315{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003316 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003317
3318 BT_DBG("");
3319
Johan Hedberg1707c602013-03-15 17:07:15 -05003320 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003321 MGMT_OP_USER_PASSKEY_REPLY,
3322 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003323}
3324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003325static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003326 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003327{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003328 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003329
3330 BT_DBG("");
3331
Johan Hedberg1707c602013-03-15 17:07:15 -05003332 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003333 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3334 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003335}
3336
Johan Hedberg13928972013-03-15 17:07:00 -05003337static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003338{
Johan Hedberg13928972013-03-15 17:07:00 -05003339 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003340 struct hci_cp_write_local_name cp;
3341
Johan Hedberg13928972013-03-15 17:07:00 -05003342 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003343
Johan Hedberg890ea892013-03-15 17:06:52 -05003344 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003345}
3346
Johan Hedberg13928972013-03-15 17:07:00 -05003347static void set_name_complete(struct hci_dev *hdev, u8 status)
3348{
3349 struct mgmt_cp_set_local_name *cp;
3350 struct pending_cmd *cmd;
3351
3352 BT_DBG("status 0x%02x", status);
3353
3354 hci_dev_lock(hdev);
3355
3356 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3357 if (!cmd)
3358 goto unlock;
3359
3360 cp = cmd->param;
3361
3362 if (status)
3363 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3364 mgmt_status(status));
3365 else
3366 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3367 cp, sizeof(*cp));
3368
3369 mgmt_pending_remove(cmd);
3370
3371unlock:
3372 hci_dev_unlock(hdev);
3373}
3374
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003375static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003376 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003377{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003378 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003379 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003380 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003381 int err;
3382
3383 BT_DBG("");
3384
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003385 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003386
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003387 /* If the old values are the same as the new ones just return a
3388 * direct command complete event.
3389 */
3390 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3391 !memcmp(hdev->short_name, cp->short_name,
3392 sizeof(hdev->short_name))) {
3393 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3394 data, len);
3395 goto failed;
3396 }
3397
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003398 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003399
Johan Hedbergb5235a62012-02-21 14:32:24 +02003400 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003401 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003402
3403 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003404 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003405 if (err < 0)
3406 goto failed;
3407
3408 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003409 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003410
Johan Hedbergb5235a62012-02-21 14:32:24 +02003411 goto failed;
3412 }
3413
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003414 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003415 if (!cmd) {
3416 err = -ENOMEM;
3417 goto failed;
3418 }
3419
Johan Hedberg13928972013-03-15 17:07:00 -05003420 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3421
Johan Hedberg890ea892013-03-15 17:06:52 -05003422 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003423
3424 if (lmp_bredr_capable(hdev)) {
3425 update_name(&req);
3426 update_eir(&req);
3427 }
3428
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003429 /* The name is stored in the scan response data and so
3430 * no need to udpate the advertising data here.
3431 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003432 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003433 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003434
Johan Hedberg13928972013-03-15 17:07:00 -05003435 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003436 if (err < 0)
3437 mgmt_pending_remove(cmd);
3438
3439failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003440 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003441 return err;
3442}
3443
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003444static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003445 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003446{
Szymon Jancc35938b2011-03-22 13:12:21 +01003447 struct pending_cmd *cmd;
3448 int err;
3449
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003450 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003451
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003452 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003453
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003454 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003455 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003456 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003457 goto unlock;
3458 }
3459
Andre Guedes9a1a1992012-07-24 15:03:48 -03003460 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003461 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003462 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003463 goto unlock;
3464 }
3465
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003466 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003467 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003468 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003469 goto unlock;
3470 }
3471
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003472 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003473 if (!cmd) {
3474 err = -ENOMEM;
3475 goto unlock;
3476 }
3477
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003478 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3479 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3480 0, NULL);
3481 else
3482 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3483
Szymon Jancc35938b2011-03-22 13:12:21 +01003484 if (err < 0)
3485 mgmt_pending_remove(cmd);
3486
3487unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003488 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003489 return err;
3490}
3491
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003492static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003493 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003494{
Szymon Janc2763eda2011-03-22 13:12:22 +01003495 int err;
3496
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003497 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003498
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003499 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003500
Marcel Holtmannec109112014-01-10 02:07:30 -08003501 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3502 struct mgmt_cp_add_remote_oob_data *cp = data;
3503 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003504
Marcel Holtmannec109112014-01-10 02:07:30 -08003505 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3506 cp->hash, cp->randomizer);
3507 if (err < 0)
3508 status = MGMT_STATUS_FAILED;
3509 else
3510 status = MGMT_STATUS_SUCCESS;
3511
3512 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3513 status, &cp->addr, sizeof(cp->addr));
3514 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3515 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3516 u8 status;
3517
3518 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3519 cp->hash192,
3520 cp->randomizer192,
3521 cp->hash256,
3522 cp->randomizer256);
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 {
3531 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3532 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3533 MGMT_STATUS_INVALID_PARAMS);
3534 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003535
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003536 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003537 return err;
3538}
3539
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003540static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003541 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003542{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003543 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003544 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003545 int err;
3546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003547 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003548
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003549 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003550
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003551 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003552 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003553 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003554 else
Szymon Janca6785be2012-12-13 15:11:21 +01003555 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003556
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003557 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003558 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003559
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003560 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003561 return err;
3562}
3563
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003564static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3565{
3566 struct pending_cmd *cmd;
3567 u8 type;
3568 int err;
3569
3570 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3571
3572 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3573 if (!cmd)
3574 return -ENOENT;
3575
3576 type = hdev->discovery.type;
3577
3578 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3579 &type, sizeof(type));
3580 mgmt_pending_remove(cmd);
3581
3582 return err;
3583}
3584
Andre Guedes7c307722013-04-30 15:29:28 -03003585static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3586{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003587 unsigned long timeout = 0;
3588
Andre Guedes7c307722013-04-30 15:29:28 -03003589 BT_DBG("status %d", status);
3590
3591 if (status) {
3592 hci_dev_lock(hdev);
3593 mgmt_start_discovery_failed(hdev, status);
3594 hci_dev_unlock(hdev);
3595 return;
3596 }
3597
3598 hci_dev_lock(hdev);
3599 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3600 hci_dev_unlock(hdev);
3601
3602 switch (hdev->discovery.type) {
3603 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003604 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003605 break;
3606
3607 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003608 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003609 break;
3610
3611 case DISCOV_TYPE_BREDR:
3612 break;
3613
3614 default:
3615 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3616 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003617
3618 if (!timeout)
3619 return;
3620
3621 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003622}
3623
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003624static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003625 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003626{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003627 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003628 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003629 struct hci_cp_le_set_scan_param param_cp;
3630 struct hci_cp_le_set_scan_enable enable_cp;
3631 struct hci_cp_inquiry inq_cp;
3632 struct hci_request req;
3633 /* General inquiry access code (GIAC) */
3634 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003635 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003636 int err;
3637
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003638 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003639
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003640 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003641
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003642 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003643 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003644 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003645 goto failed;
3646 }
3647
Andre Guedes642be6c2012-03-21 00:03:37 -03003648 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3649 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3650 MGMT_STATUS_BUSY);
3651 goto failed;
3652 }
3653
Johan Hedbergff9ef572012-01-04 14:23:45 +02003654 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003655 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003656 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003657 goto failed;
3658 }
3659
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003660 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003661 if (!cmd) {
3662 err = -ENOMEM;
3663 goto failed;
3664 }
3665
Andre Guedes4aab14e2012-02-17 20:39:36 -03003666 hdev->discovery.type = cp->type;
3667
Andre Guedes7c307722013-04-30 15:29:28 -03003668 hci_req_init(&req, hdev);
3669
Andre Guedes4aab14e2012-02-17 20:39:36 -03003670 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003671 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003672 status = mgmt_bredr_support(hdev);
3673 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003674 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003675 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003676 mgmt_pending_remove(cmd);
3677 goto failed;
3678 }
3679
Andre Guedes7c307722013-04-30 15:29:28 -03003680 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3681 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3682 MGMT_STATUS_BUSY);
3683 mgmt_pending_remove(cmd);
3684 goto failed;
3685 }
3686
3687 hci_inquiry_cache_flush(hdev);
3688
3689 memset(&inq_cp, 0, sizeof(inq_cp));
3690 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003691 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003692 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003693 break;
3694
3695 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003696 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003697 status = mgmt_le_support(hdev);
3698 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003699 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003700 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003701 mgmt_pending_remove(cmd);
3702 goto failed;
3703 }
3704
Andre Guedes7c307722013-04-30 15:29:28 -03003705 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003706 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003707 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3708 MGMT_STATUS_NOT_SUPPORTED);
3709 mgmt_pending_remove(cmd);
3710 goto failed;
3711 }
3712
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003713 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003714 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3715 MGMT_STATUS_REJECTED);
3716 mgmt_pending_remove(cmd);
3717 goto failed;
3718 }
3719
Andre Guedesc54c3862014-02-26 20:21:50 -03003720 /* If controller is scanning, it means the background scanning
3721 * is running. Thus, we should temporarily stop it in order to
3722 * set the discovery scanning parameters.
3723 */
3724 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3725 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003726
3727 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003728
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003729 /* All active scans will be done with either a resolvable
3730 * private address (when privacy feature has been enabled)
3731 * or unresolvable private address.
3732 */
3733 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003734 if (err < 0) {
3735 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3736 MGMT_STATUS_FAILED);
3737 mgmt_pending_remove(cmd);
3738 goto failed;
3739 }
3740
Andre Guedes7c307722013-04-30 15:29:28 -03003741 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003742 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3743 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003744 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003745 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3746 &param_cp);
3747
3748 memset(&enable_cp, 0, sizeof(enable_cp));
3749 enable_cp.enable = LE_SCAN_ENABLE;
3750 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3751 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3752 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003753 break;
3754
Andre Guedesf39799f2012-02-17 20:39:35 -03003755 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003756 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3757 MGMT_STATUS_INVALID_PARAMS);
3758 mgmt_pending_remove(cmd);
3759 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003760 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003761
Andre Guedes7c307722013-04-30 15:29:28 -03003762 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003763 if (err < 0)
3764 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003765 else
3766 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003767
3768failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003769 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003770 return err;
3771}
3772
Andre Guedes1183fdc2013-04-30 15:29:35 -03003773static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3774{
3775 struct pending_cmd *cmd;
3776 int err;
3777
3778 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3779 if (!cmd)
3780 return -ENOENT;
3781
3782 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3783 &hdev->discovery.type, sizeof(hdev->discovery.type));
3784 mgmt_pending_remove(cmd);
3785
3786 return err;
3787}
3788
Andre Guedes0e05bba2013-04-30 15:29:33 -03003789static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3790{
3791 BT_DBG("status %d", status);
3792
3793 hci_dev_lock(hdev);
3794
3795 if (status) {
3796 mgmt_stop_discovery_failed(hdev, status);
3797 goto unlock;
3798 }
3799
3800 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3801
3802unlock:
3803 hci_dev_unlock(hdev);
3804}
3805
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003806static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003807 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003808{
Johan Hedbergd9306502012-02-20 23:25:18 +02003809 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003810 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003811 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003812 int err;
3813
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003814 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003815
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003816 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003817
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003818 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003819 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003820 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3821 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003822 goto unlock;
3823 }
3824
3825 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003826 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003827 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3828 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003829 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003830 }
3831
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003832 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003833 if (!cmd) {
3834 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003835 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003836 }
3837
Andre Guedes0e05bba2013-04-30 15:29:33 -03003838 hci_req_init(&req, hdev);
3839
Johan Hedberg21a60d32014-06-10 14:05:58 +03003840 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003841
Johan Hedberg21a60d32014-06-10 14:05:58 +03003842 err = hci_req_run(&req, stop_discovery_complete);
3843 if (!err) {
3844 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003845 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003846 }
3847
Johan Hedberg21a60d32014-06-10 14:05:58 +03003848 mgmt_pending_remove(cmd);
3849
3850 /* If no HCI commands were sent we're done */
3851 if (err == -ENODATA) {
3852 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3853 &mgmt_cp->type, sizeof(mgmt_cp->type));
3854 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3855 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003856
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003857unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003858 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003859 return err;
3860}
3861
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003862static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003863 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003864{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003865 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003866 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003867 int err;
3868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003869 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003870
Johan Hedberg561aafb2012-01-04 13:31:59 +02003871 hci_dev_lock(hdev);
3872
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003873 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003874 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3875 MGMT_STATUS_FAILED, &cp->addr,
3876 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003877 goto failed;
3878 }
3879
Johan Hedberga198e7b2012-02-17 14:27:06 +02003880 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003881 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003882 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3883 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3884 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003885 goto failed;
3886 }
3887
3888 if (cp->name_known) {
3889 e->name_state = NAME_KNOWN;
3890 list_del(&e->list);
3891 } else {
3892 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003893 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003894 }
3895
Johan Hedberge3846622013-01-09 15:29:33 +02003896 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3897 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003898
3899failed:
3900 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003901 return err;
3902}
3903
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003904static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003905 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003906{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003907 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003908 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003909 int err;
3910
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003911 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003912
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003913 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003914 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3915 MGMT_STATUS_INVALID_PARAMS,
3916 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003917
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003918 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003919
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003920 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003921 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003922 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003923 goto done;
3924 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003925
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003926 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3927 sk);
3928 status = MGMT_STATUS_SUCCESS;
3929
3930done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003931 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003932 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003933
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003934 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003935
3936 return err;
3937}
3938
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003939static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003940 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003941{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003942 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003943 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003944 int err;
3945
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003946 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003947
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003948 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003949 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3950 MGMT_STATUS_INVALID_PARAMS,
3951 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003952
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003953 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003954
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003955 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003956 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003957 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003958 goto done;
3959 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003960
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003961 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3962 sk);
3963 status = MGMT_STATUS_SUCCESS;
3964
3965done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003966 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003967 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003968
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003969 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003970
3971 return err;
3972}
3973
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003974static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3975 u16 len)
3976{
3977 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003978 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003979 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003980 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003981
3982 BT_DBG("%s", hdev->name);
3983
Szymon Jancc72d4b82012-03-16 16:02:57 +01003984 source = __le16_to_cpu(cp->source);
3985
3986 if (source > 0x0002)
3987 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3988 MGMT_STATUS_INVALID_PARAMS);
3989
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003990 hci_dev_lock(hdev);
3991
Szymon Jancc72d4b82012-03-16 16:02:57 +01003992 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003993 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3994 hdev->devid_product = __le16_to_cpu(cp->product);
3995 hdev->devid_version = __le16_to_cpu(cp->version);
3996
3997 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3998
Johan Hedberg890ea892013-03-15 17:06:52 -05003999 hci_req_init(&req, hdev);
4000 update_eir(&req);
4001 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004002
4003 hci_dev_unlock(hdev);
4004
4005 return err;
4006}
4007
Johan Hedberg4375f102013-09-25 13:26:10 +03004008static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4009{
4010 struct cmd_lookup match = { NULL, hdev };
4011
4012 if (status) {
4013 u8 mgmt_err = mgmt_status(status);
4014
4015 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4016 cmd_status_rsp, &mgmt_err);
4017 return;
4018 }
4019
4020 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4021 &match);
4022
4023 new_settings(hdev, match.sk);
4024
4025 if (match.sk)
4026 sock_put(match.sk);
4027}
4028
Marcel Holtmann21b51872013-10-10 09:47:53 -07004029static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4030 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004031{
4032 struct mgmt_mode *cp = data;
4033 struct pending_cmd *cmd;
4034 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004035 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004036 int err;
4037
4038 BT_DBG("request for %s", hdev->name);
4039
Johan Hedberge6fe7982013-10-02 15:45:22 +03004040 status = mgmt_le_support(hdev);
4041 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004042 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004043 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004044
4045 if (cp->val != 0x00 && cp->val != 0x01)
4046 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4047 MGMT_STATUS_INVALID_PARAMS);
4048
4049 hci_dev_lock(hdev);
4050
4051 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004052 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004053
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004054 /* The following conditions are ones which mean that we should
4055 * not do any HCI communication but directly send a mgmt
4056 * response to user space (after toggling the flag if
4057 * necessary).
4058 */
4059 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004060 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004061 bool changed = false;
4062
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004063 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4064 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004065 changed = true;
4066 }
4067
4068 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4069 if (err < 0)
4070 goto unlock;
4071
4072 if (changed)
4073 err = new_settings(hdev, sk);
4074
4075 goto unlock;
4076 }
4077
4078 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4079 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4080 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4081 MGMT_STATUS_BUSY);
4082 goto unlock;
4083 }
4084
4085 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4086 if (!cmd) {
4087 err = -ENOMEM;
4088 goto unlock;
4089 }
4090
4091 hci_req_init(&req, hdev);
4092
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004093 if (val)
4094 enable_advertising(&req);
4095 else
4096 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004097
4098 err = hci_req_run(&req, set_advertising_complete);
4099 if (err < 0)
4100 mgmt_pending_remove(cmd);
4101
4102unlock:
4103 hci_dev_unlock(hdev);
4104 return err;
4105}
4106
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004107static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4108 void *data, u16 len)
4109{
4110 struct mgmt_cp_set_static_address *cp = data;
4111 int err;
4112
4113 BT_DBG("%s", hdev->name);
4114
Marcel Holtmann62af4442013-10-02 22:10:32 -07004115 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004116 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004117 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004118
4119 if (hdev_is_powered(hdev))
4120 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4121 MGMT_STATUS_REJECTED);
4122
4123 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4124 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4125 return cmd_status(sk, hdev->id,
4126 MGMT_OP_SET_STATIC_ADDRESS,
4127 MGMT_STATUS_INVALID_PARAMS);
4128
4129 /* Two most significant bits shall be set */
4130 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4131 return cmd_status(sk, hdev->id,
4132 MGMT_OP_SET_STATIC_ADDRESS,
4133 MGMT_STATUS_INVALID_PARAMS);
4134 }
4135
4136 hci_dev_lock(hdev);
4137
4138 bacpy(&hdev->static_addr, &cp->bdaddr);
4139
4140 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4141
4142 hci_dev_unlock(hdev);
4143
4144 return err;
4145}
4146
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004147static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4148 void *data, u16 len)
4149{
4150 struct mgmt_cp_set_scan_params *cp = data;
4151 __u16 interval, window;
4152 int err;
4153
4154 BT_DBG("%s", hdev->name);
4155
4156 if (!lmp_le_capable(hdev))
4157 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4158 MGMT_STATUS_NOT_SUPPORTED);
4159
4160 interval = __le16_to_cpu(cp->interval);
4161
4162 if (interval < 0x0004 || interval > 0x4000)
4163 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4164 MGMT_STATUS_INVALID_PARAMS);
4165
4166 window = __le16_to_cpu(cp->window);
4167
4168 if (window < 0x0004 || window > 0x4000)
4169 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4170 MGMT_STATUS_INVALID_PARAMS);
4171
Marcel Holtmann899e1072013-10-14 09:55:32 -07004172 if (window > interval)
4173 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4174 MGMT_STATUS_INVALID_PARAMS);
4175
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004176 hci_dev_lock(hdev);
4177
4178 hdev->le_scan_interval = interval;
4179 hdev->le_scan_window = window;
4180
4181 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4182
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004183 /* If background scan is running, restart it so new parameters are
4184 * loaded.
4185 */
4186 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4187 hdev->discovery.state == DISCOVERY_STOPPED) {
4188 struct hci_request req;
4189
4190 hci_req_init(&req, hdev);
4191
4192 hci_req_add_le_scan_disable(&req);
4193 hci_req_add_le_passive_scan(&req);
4194
4195 hci_req_run(&req, NULL);
4196 }
4197
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004198 hci_dev_unlock(hdev);
4199
4200 return err;
4201}
4202
Johan Hedberg33e38b32013-03-15 17:07:05 -05004203static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4204{
4205 struct pending_cmd *cmd;
4206
4207 BT_DBG("status 0x%02x", status);
4208
4209 hci_dev_lock(hdev);
4210
4211 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4212 if (!cmd)
4213 goto unlock;
4214
4215 if (status) {
4216 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4217 mgmt_status(status));
4218 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004219 struct mgmt_mode *cp = cmd->param;
4220
4221 if (cp->val)
4222 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4223 else
4224 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4225
Johan Hedberg33e38b32013-03-15 17:07:05 -05004226 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4227 new_settings(hdev, cmd->sk);
4228 }
4229
4230 mgmt_pending_remove(cmd);
4231
4232unlock:
4233 hci_dev_unlock(hdev);
4234}
4235
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004236static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004237 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004238{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004239 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004240 struct pending_cmd *cmd;
4241 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004242 int err;
4243
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004244 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004245
Johan Hedberg56f87902013-10-02 13:43:13 +03004246 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4247 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004248 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4249 MGMT_STATUS_NOT_SUPPORTED);
4250
Johan Hedberga7e80f22013-01-09 16:05:19 +02004251 if (cp->val != 0x00 && cp->val != 0x01)
4252 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4253 MGMT_STATUS_INVALID_PARAMS);
4254
Johan Hedberg5400c042012-02-21 16:40:33 +02004255 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004256 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004257 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004258
4259 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004260 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004261 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004262
4263 hci_dev_lock(hdev);
4264
Johan Hedberg05cbf292013-03-15 17:07:07 -05004265 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4266 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4267 MGMT_STATUS_BUSY);
4268 goto unlock;
4269 }
4270
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004271 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4272 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4273 hdev);
4274 goto unlock;
4275 }
4276
Johan Hedberg33e38b32013-03-15 17:07:05 -05004277 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4278 data, len);
4279 if (!cmd) {
4280 err = -ENOMEM;
4281 goto unlock;
4282 }
4283
4284 hci_req_init(&req, hdev);
4285
Johan Hedberg406d7802013-03-15 17:07:09 -05004286 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004287
4288 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004289 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004290 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004291 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004292 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004293 }
4294
Johan Hedberg33e38b32013-03-15 17:07:05 -05004295unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004296 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004297
Antti Julkuf6422ec2011-06-22 13:11:56 +03004298 return err;
4299}
4300
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004301static void set_bredr_scan(struct hci_request *req)
4302{
4303 struct hci_dev *hdev = req->hdev;
4304 u8 scan = 0;
4305
4306 /* Ensure that fast connectable is disabled. This function will
4307 * not do anything if the page scan parameters are already what
4308 * they should be.
4309 */
4310 write_fast_connectable(req, false);
4311
4312 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4313 scan |= SCAN_PAGE;
4314 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4315 scan |= SCAN_INQUIRY;
4316
4317 if (scan)
4318 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4319}
4320
Johan Hedberg0663ca22013-10-02 13:43:14 +03004321static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4322{
4323 struct pending_cmd *cmd;
4324
4325 BT_DBG("status 0x%02x", status);
4326
4327 hci_dev_lock(hdev);
4328
4329 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4330 if (!cmd)
4331 goto unlock;
4332
4333 if (status) {
4334 u8 mgmt_err = mgmt_status(status);
4335
4336 /* We need to restore the flag if related HCI commands
4337 * failed.
4338 */
4339 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4340
4341 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4342 } else {
4343 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4344 new_settings(hdev, cmd->sk);
4345 }
4346
4347 mgmt_pending_remove(cmd);
4348
4349unlock:
4350 hci_dev_unlock(hdev);
4351}
4352
4353static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4354{
4355 struct mgmt_mode *cp = data;
4356 struct pending_cmd *cmd;
4357 struct hci_request req;
4358 int err;
4359
4360 BT_DBG("request for %s", hdev->name);
4361
4362 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4363 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4364 MGMT_STATUS_NOT_SUPPORTED);
4365
4366 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4367 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4368 MGMT_STATUS_REJECTED);
4369
4370 if (cp->val != 0x00 && cp->val != 0x01)
4371 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4372 MGMT_STATUS_INVALID_PARAMS);
4373
4374 hci_dev_lock(hdev);
4375
4376 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4377 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4378 goto unlock;
4379 }
4380
4381 if (!hdev_is_powered(hdev)) {
4382 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004383 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4384 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4385 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4386 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4387 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4388 }
4389
4390 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4391
4392 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4393 if (err < 0)
4394 goto unlock;
4395
4396 err = new_settings(hdev, sk);
4397 goto unlock;
4398 }
4399
4400 /* Reject disabling when powered on */
4401 if (!cp->val) {
4402 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4403 MGMT_STATUS_REJECTED);
4404 goto unlock;
4405 }
4406
4407 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4408 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4409 MGMT_STATUS_BUSY);
4410 goto unlock;
4411 }
4412
4413 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4414 if (!cmd) {
4415 err = -ENOMEM;
4416 goto unlock;
4417 }
4418
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004419 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004420 * generates the correct flags.
4421 */
4422 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4423
4424 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004425
4426 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4427 set_bredr_scan(&req);
4428
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004429 /* Since only the advertising data flags will change, there
4430 * is no need to update the scan response data.
4431 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004432 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004433
Johan Hedberg0663ca22013-10-02 13:43:14 +03004434 err = hci_req_run(&req, set_bredr_complete);
4435 if (err < 0)
4436 mgmt_pending_remove(cmd);
4437
4438unlock:
4439 hci_dev_unlock(hdev);
4440 return err;
4441}
4442
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004443static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4444 void *data, u16 len)
4445{
4446 struct mgmt_mode *cp = data;
4447 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004448 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004449 int err;
4450
4451 BT_DBG("request for %s", hdev->name);
4452
4453 status = mgmt_bredr_support(hdev);
4454 if (status)
4455 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4456 status);
4457
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004458 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004459 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004460 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4461 MGMT_STATUS_NOT_SUPPORTED);
4462
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004463 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004464 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4465 MGMT_STATUS_INVALID_PARAMS);
4466
4467 hci_dev_lock(hdev);
4468
4469 if (!hdev_is_powered(hdev)) {
4470 bool changed;
4471
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004472 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004473 changed = !test_and_set_bit(HCI_SC_ENABLED,
4474 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004475 if (cp->val == 0x02)
4476 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4477 else
4478 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4479 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004480 changed = test_and_clear_bit(HCI_SC_ENABLED,
4481 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004482 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4483 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004484
4485 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4486 if (err < 0)
4487 goto failed;
4488
4489 if (changed)
4490 err = new_settings(hdev, sk);
4491
4492 goto failed;
4493 }
4494
4495 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4496 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4497 MGMT_STATUS_BUSY);
4498 goto failed;
4499 }
4500
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004501 val = !!cp->val;
4502
4503 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4504 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004505 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4506 goto failed;
4507 }
4508
4509 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4510 if (!cmd) {
4511 err = -ENOMEM;
4512 goto failed;
4513 }
4514
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004515 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004516 if (err < 0) {
4517 mgmt_pending_remove(cmd);
4518 goto failed;
4519 }
4520
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004521 if (cp->val == 0x02)
4522 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4523 else
4524 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4525
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004526failed:
4527 hci_dev_unlock(hdev);
4528 return err;
4529}
4530
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004531static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4532 void *data, u16 len)
4533{
4534 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004535 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004536 int err;
4537
4538 BT_DBG("request for %s", hdev->name);
4539
Johan Hedbergb97109792014-06-24 14:00:28 +03004540 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004541 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4542 MGMT_STATUS_INVALID_PARAMS);
4543
4544 hci_dev_lock(hdev);
4545
4546 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004547 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4548 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004549 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004550 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4551 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004552
Johan Hedbergb97109792014-06-24 14:00:28 +03004553 if (cp->val == 0x02)
4554 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4555 &hdev->dev_flags);
4556 else
4557 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4558 &hdev->dev_flags);
4559
4560 if (hdev_is_powered(hdev) && use_changed &&
4561 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4562 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4563 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4564 sizeof(mode), &mode);
4565 }
4566
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004567 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4568 if (err < 0)
4569 goto unlock;
4570
4571 if (changed)
4572 err = new_settings(hdev, sk);
4573
4574unlock:
4575 hci_dev_unlock(hdev);
4576 return err;
4577}
4578
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004579static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4580 u16 len)
4581{
4582 struct mgmt_cp_set_privacy *cp = cp_data;
4583 bool changed;
4584 int err;
4585
4586 BT_DBG("request for %s", hdev->name);
4587
4588 if (!lmp_le_capable(hdev))
4589 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4590 MGMT_STATUS_NOT_SUPPORTED);
4591
4592 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4593 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4594 MGMT_STATUS_INVALID_PARAMS);
4595
4596 if (hdev_is_powered(hdev))
4597 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4598 MGMT_STATUS_REJECTED);
4599
4600 hci_dev_lock(hdev);
4601
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004602 /* If user space supports this command it is also expected to
4603 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4604 */
4605 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4606
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004607 if (cp->privacy) {
4608 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4609 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4610 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4611 } else {
4612 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4613 memset(hdev->irk, 0, sizeof(hdev->irk));
4614 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4615 }
4616
4617 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4618 if (err < 0)
4619 goto unlock;
4620
4621 if (changed)
4622 err = new_settings(hdev, sk);
4623
4624unlock:
4625 hci_dev_unlock(hdev);
4626 return err;
4627}
4628
Johan Hedberg41edf162014-02-18 10:19:35 +02004629static bool irk_is_valid(struct mgmt_irk_info *irk)
4630{
4631 switch (irk->addr.type) {
4632 case BDADDR_LE_PUBLIC:
4633 return true;
4634
4635 case BDADDR_LE_RANDOM:
4636 /* Two most significant bits shall be set */
4637 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4638 return false;
4639 return true;
4640 }
4641
4642 return false;
4643}
4644
4645static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4646 u16 len)
4647{
4648 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004649 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4650 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004651 u16 irk_count, expected_len;
4652 int i, err;
4653
4654 BT_DBG("request for %s", hdev->name);
4655
4656 if (!lmp_le_capable(hdev))
4657 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4658 MGMT_STATUS_NOT_SUPPORTED);
4659
4660 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004661 if (irk_count > max_irk_count) {
4662 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4663 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4664 MGMT_STATUS_INVALID_PARAMS);
4665 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004666
4667 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4668 if (expected_len != len) {
4669 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004670 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004671 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4672 MGMT_STATUS_INVALID_PARAMS);
4673 }
4674
4675 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4676
4677 for (i = 0; i < irk_count; i++) {
4678 struct mgmt_irk_info *key = &cp->irks[i];
4679
4680 if (!irk_is_valid(key))
4681 return cmd_status(sk, hdev->id,
4682 MGMT_OP_LOAD_IRKS,
4683 MGMT_STATUS_INVALID_PARAMS);
4684 }
4685
4686 hci_dev_lock(hdev);
4687
4688 hci_smp_irks_clear(hdev);
4689
4690 for (i = 0; i < irk_count; i++) {
4691 struct mgmt_irk_info *irk = &cp->irks[i];
4692 u8 addr_type;
4693
4694 if (irk->addr.type == BDADDR_LE_PUBLIC)
4695 addr_type = ADDR_LE_DEV_PUBLIC;
4696 else
4697 addr_type = ADDR_LE_DEV_RANDOM;
4698
4699 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4700 BDADDR_ANY);
4701 }
4702
4703 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4704
4705 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4706
4707 hci_dev_unlock(hdev);
4708
4709 return err;
4710}
4711
Johan Hedberg3f706b72013-01-20 14:27:16 +02004712static bool ltk_is_valid(struct mgmt_ltk_info *key)
4713{
4714 if (key->master != 0x00 && key->master != 0x01)
4715 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004716
4717 switch (key->addr.type) {
4718 case BDADDR_LE_PUBLIC:
4719 return true;
4720
4721 case BDADDR_LE_RANDOM:
4722 /* Two most significant bits shall be set */
4723 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4724 return false;
4725 return true;
4726 }
4727
4728 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004729}
4730
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004731static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004732 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004733{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004734 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004735 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4736 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004737 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004738 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004739
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004740 BT_DBG("request for %s", hdev->name);
4741
4742 if (!lmp_le_capable(hdev))
4743 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4744 MGMT_STATUS_NOT_SUPPORTED);
4745
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004746 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004747 if (key_count > max_key_count) {
4748 BT_ERR("load_ltks: too big key_count value %u", key_count);
4749 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4750 MGMT_STATUS_INVALID_PARAMS);
4751 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004752
4753 expected_len = sizeof(*cp) + key_count *
4754 sizeof(struct mgmt_ltk_info);
4755 if (expected_len != len) {
4756 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004757 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004758 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004759 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004760 }
4761
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004762 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004763
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004764 for (i = 0; i < key_count; i++) {
4765 struct mgmt_ltk_info *key = &cp->keys[i];
4766
Johan Hedberg3f706b72013-01-20 14:27:16 +02004767 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004768 return cmd_status(sk, hdev->id,
4769 MGMT_OP_LOAD_LONG_TERM_KEYS,
4770 MGMT_STATUS_INVALID_PARAMS);
4771 }
4772
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004773 hci_dev_lock(hdev);
4774
4775 hci_smp_ltks_clear(hdev);
4776
4777 for (i = 0; i < key_count; i++) {
4778 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004779 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004780
4781 if (key->addr.type == BDADDR_LE_PUBLIC)
4782 addr_type = ADDR_LE_DEV_PUBLIC;
4783 else
4784 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004785
4786 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004787 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004788 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004789 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004790
Johan Hedberg61b43352014-05-29 19:36:53 +03004791 switch (key->type) {
4792 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004793 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004794 break;
4795 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004796 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004797 break;
4798 default:
4799 continue;
4800 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004801
Johan Hedberg35d70272014-02-19 14:57:47 +02004802 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004803 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004804 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004805 }
4806
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004807 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4808 NULL, 0);
4809
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004810 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004811
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004812 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004813}
4814
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004815struct cmd_conn_lookup {
4816 struct hci_conn *conn;
4817 bool valid_tx_power;
4818 u8 mgmt_status;
4819};
4820
4821static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4822{
4823 struct cmd_conn_lookup *match = data;
4824 struct mgmt_cp_get_conn_info *cp;
4825 struct mgmt_rp_get_conn_info rp;
4826 struct hci_conn *conn = cmd->user_data;
4827
4828 if (conn != match->conn)
4829 return;
4830
4831 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4832
4833 memset(&rp, 0, sizeof(rp));
4834 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4835 rp.addr.type = cp->addr.type;
4836
4837 if (!match->mgmt_status) {
4838 rp.rssi = conn->rssi;
4839
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004840 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004841 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004842 rp.max_tx_power = conn->max_tx_power;
4843 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004844 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004845 rp.max_tx_power = HCI_TX_POWER_INVALID;
4846 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004847 }
4848
4849 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4850 match->mgmt_status, &rp, sizeof(rp));
4851
4852 hci_conn_drop(conn);
4853
4854 mgmt_pending_remove(cmd);
4855}
4856
4857static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4858{
4859 struct hci_cp_read_rssi *cp;
4860 struct hci_conn *conn;
4861 struct cmd_conn_lookup match;
4862 u16 handle;
4863
4864 BT_DBG("status 0x%02x", status);
4865
4866 hci_dev_lock(hdev);
4867
4868 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004869 * otherwise we assume it's not valid. At the moment we assume that
4870 * either both or none of current and max values are valid to keep code
4871 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004872 */
4873 match.valid_tx_power = !status;
4874
4875 /* Commands sent in request are either Read RSSI or Read Transmit Power
4876 * Level so we check which one was last sent to retrieve connection
4877 * handle. Both commands have handle as first parameter so it's safe to
4878 * cast data on the same command struct.
4879 *
4880 * First command sent is always Read RSSI and we fail only if it fails.
4881 * In other case we simply override error to indicate success as we
4882 * already remembered if TX power value is actually valid.
4883 */
4884 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4885 if (!cp) {
4886 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4887 status = 0;
4888 }
4889
4890 if (!cp) {
4891 BT_ERR("invalid sent_cmd in response");
4892 goto unlock;
4893 }
4894
4895 handle = __le16_to_cpu(cp->handle);
4896 conn = hci_conn_hash_lookup_handle(hdev, handle);
4897 if (!conn) {
4898 BT_ERR("unknown handle (%d) in response", handle);
4899 goto unlock;
4900 }
4901
4902 match.conn = conn;
4903 match.mgmt_status = mgmt_status(status);
4904
4905 /* Cache refresh is complete, now reply for mgmt request for given
4906 * connection only.
4907 */
4908 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4909 get_conn_info_complete, &match);
4910
4911unlock:
4912 hci_dev_unlock(hdev);
4913}
4914
4915static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4916 u16 len)
4917{
4918 struct mgmt_cp_get_conn_info *cp = data;
4919 struct mgmt_rp_get_conn_info rp;
4920 struct hci_conn *conn;
4921 unsigned long conn_info_age;
4922 int err = 0;
4923
4924 BT_DBG("%s", hdev->name);
4925
4926 memset(&rp, 0, sizeof(rp));
4927 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4928 rp.addr.type = cp->addr.type;
4929
4930 if (!bdaddr_type_is_valid(cp->addr.type))
4931 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4932 MGMT_STATUS_INVALID_PARAMS,
4933 &rp, sizeof(rp));
4934
4935 hci_dev_lock(hdev);
4936
4937 if (!hdev_is_powered(hdev)) {
4938 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4939 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4940 goto unlock;
4941 }
4942
4943 if (cp->addr.type == BDADDR_BREDR)
4944 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4945 &cp->addr.bdaddr);
4946 else
4947 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4948
4949 if (!conn || conn->state != BT_CONNECTED) {
4950 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4951 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4952 goto unlock;
4953 }
4954
4955 /* To avoid client trying to guess when to poll again for information we
4956 * calculate conn info age as random value between min/max set in hdev.
4957 */
4958 conn_info_age = hdev->conn_info_min_age +
4959 prandom_u32_max(hdev->conn_info_max_age -
4960 hdev->conn_info_min_age);
4961
4962 /* Query controller to refresh cached values if they are too old or were
4963 * never read.
4964 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004965 if (time_after(jiffies, conn->conn_info_timestamp +
4966 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004967 !conn->conn_info_timestamp) {
4968 struct hci_request req;
4969 struct hci_cp_read_tx_power req_txp_cp;
4970 struct hci_cp_read_rssi req_rssi_cp;
4971 struct pending_cmd *cmd;
4972
4973 hci_req_init(&req, hdev);
4974 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4975 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4976 &req_rssi_cp);
4977
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004978 /* For LE links TX power does not change thus we don't need to
4979 * query for it once value is known.
4980 */
4981 if (!bdaddr_type_is_le(cp->addr.type) ||
4982 conn->tx_power == HCI_TX_POWER_INVALID) {
4983 req_txp_cp.handle = cpu_to_le16(conn->handle);
4984 req_txp_cp.type = 0x00;
4985 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4986 sizeof(req_txp_cp), &req_txp_cp);
4987 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004988
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004989 /* Max TX power needs to be read only once per connection */
4990 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4991 req_txp_cp.handle = cpu_to_le16(conn->handle);
4992 req_txp_cp.type = 0x01;
4993 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4994 sizeof(req_txp_cp), &req_txp_cp);
4995 }
4996
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004997 err = hci_req_run(&req, conn_info_refresh_complete);
4998 if (err < 0)
4999 goto unlock;
5000
5001 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5002 data, len);
5003 if (!cmd) {
5004 err = -ENOMEM;
5005 goto unlock;
5006 }
5007
5008 hci_conn_hold(conn);
5009 cmd->user_data = conn;
5010
5011 conn->conn_info_timestamp = jiffies;
5012 } else {
5013 /* Cache is valid, just reply with values cached in hci_conn */
5014 rp.rssi = conn->rssi;
5015 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005016 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005017
5018 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5019 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5020 }
5021
5022unlock:
5023 hci_dev_unlock(hdev);
5024 return err;
5025}
5026
Johan Hedberg95868422014-06-28 17:54:07 +03005027static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5028{
5029 struct mgmt_cp_get_clock_info *cp;
5030 struct mgmt_rp_get_clock_info rp;
5031 struct hci_cp_read_clock *hci_cp;
5032 struct pending_cmd *cmd;
5033 struct hci_conn *conn;
5034
5035 BT_DBG("%s status %u", hdev->name, status);
5036
5037 hci_dev_lock(hdev);
5038
5039 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5040 if (!hci_cp)
5041 goto unlock;
5042
5043 if (hci_cp->which) {
5044 u16 handle = __le16_to_cpu(hci_cp->handle);
5045 conn = hci_conn_hash_lookup_handle(hdev, handle);
5046 } else {
5047 conn = NULL;
5048 }
5049
5050 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5051 if (!cmd)
5052 goto unlock;
5053
5054 cp = cmd->param;
5055
5056 memset(&rp, 0, sizeof(rp));
5057 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5058
5059 if (status)
5060 goto send_rsp;
5061
5062 rp.local_clock = cpu_to_le32(hdev->clock);
5063
5064 if (conn) {
5065 rp.piconet_clock = cpu_to_le32(conn->clock);
5066 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5067 }
5068
5069send_rsp:
5070 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5071 &rp, sizeof(rp));
5072 mgmt_pending_remove(cmd);
5073 if (conn)
5074 hci_conn_drop(conn);
5075
5076unlock:
5077 hci_dev_unlock(hdev);
5078}
5079
5080static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5081 u16 len)
5082{
5083 struct mgmt_cp_get_clock_info *cp = data;
5084 struct mgmt_rp_get_clock_info rp;
5085 struct hci_cp_read_clock hci_cp;
5086 struct pending_cmd *cmd;
5087 struct hci_request req;
5088 struct hci_conn *conn;
5089 int err;
5090
5091 BT_DBG("%s", hdev->name);
5092
5093 memset(&rp, 0, sizeof(rp));
5094 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5095 rp.addr.type = cp->addr.type;
5096
5097 if (cp->addr.type != BDADDR_BREDR)
5098 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5099 MGMT_STATUS_INVALID_PARAMS,
5100 &rp, sizeof(rp));
5101
5102 hci_dev_lock(hdev);
5103
5104 if (!hdev_is_powered(hdev)) {
5105 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5106 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5107 goto unlock;
5108 }
5109
5110 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5111 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5112 &cp->addr.bdaddr);
5113 if (!conn || conn->state != BT_CONNECTED) {
5114 err = cmd_complete(sk, hdev->id,
5115 MGMT_OP_GET_CLOCK_INFO,
5116 MGMT_STATUS_NOT_CONNECTED,
5117 &rp, sizeof(rp));
5118 goto unlock;
5119 }
5120 } else {
5121 conn = NULL;
5122 }
5123
5124 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5125 if (!cmd) {
5126 err = -ENOMEM;
5127 goto unlock;
5128 }
5129
5130 hci_req_init(&req, hdev);
5131
5132 memset(&hci_cp, 0, sizeof(hci_cp));
5133 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5134
5135 if (conn) {
5136 hci_conn_hold(conn);
5137 cmd->user_data = conn;
5138
5139 hci_cp.handle = cpu_to_le16(conn->handle);
5140 hci_cp.which = 0x01; /* Piconet clock */
5141 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5142 }
5143
5144 err = hci_req_run(&req, get_clock_info_complete);
5145 if (err < 0)
5146 mgmt_pending_remove(cmd);
5147
5148unlock:
5149 hci_dev_unlock(hdev);
5150 return err;
5151}
5152
Marcel Holtmann8afef092014-06-29 22:28:34 +02005153static void device_added(struct sock *sk, struct hci_dev *hdev,
5154 bdaddr_t *bdaddr, u8 type, u8 action)
5155{
5156 struct mgmt_ev_device_added ev;
5157
5158 bacpy(&ev.addr.bdaddr, bdaddr);
5159 ev.addr.type = type;
5160 ev.action = action;
5161
5162 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5163}
5164
Marcel Holtmann2faade52014-06-29 19:44:03 +02005165static int add_device(struct sock *sk, struct hci_dev *hdev,
5166 void *data, u16 len)
5167{
5168 struct mgmt_cp_add_device *cp = data;
5169 u8 auto_conn, addr_type;
5170 int err;
5171
5172 BT_DBG("%s", hdev->name);
5173
5174 if (!bdaddr_type_is_le(cp->addr.type) ||
5175 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5176 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5177 MGMT_STATUS_INVALID_PARAMS,
5178 &cp->addr, sizeof(cp->addr));
5179
5180 if (cp->action != 0x00 && cp->action != 0x01)
5181 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5182 MGMT_STATUS_INVALID_PARAMS,
5183 &cp->addr, sizeof(cp->addr));
5184
5185 hci_dev_lock(hdev);
5186
5187 if (cp->addr.type == BDADDR_LE_PUBLIC)
5188 addr_type = ADDR_LE_DEV_PUBLIC;
5189 else
5190 addr_type = ADDR_LE_DEV_RANDOM;
5191
5192 if (cp->action)
5193 auto_conn = HCI_AUTO_CONN_ALWAYS;
5194 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005195 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005196
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005197 /* If the connection parameters don't exist for this device,
5198 * they will be created and configured with defaults.
5199 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005200 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5201 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005202 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5203 MGMT_STATUS_FAILED,
5204 &cp->addr, sizeof(cp->addr));
5205 goto unlock;
5206 }
5207
Marcel Holtmann8afef092014-06-29 22:28:34 +02005208 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5209
Marcel Holtmann2faade52014-06-29 19:44:03 +02005210 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5211 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5212
5213unlock:
5214 hci_dev_unlock(hdev);
5215 return err;
5216}
5217
Marcel Holtmann8afef092014-06-29 22:28:34 +02005218static void device_removed(struct sock *sk, struct hci_dev *hdev,
5219 bdaddr_t *bdaddr, u8 type)
5220{
5221 struct mgmt_ev_device_removed ev;
5222
5223 bacpy(&ev.addr.bdaddr, bdaddr);
5224 ev.addr.type = type;
5225
5226 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5227}
5228
Marcel Holtmann2faade52014-06-29 19:44:03 +02005229static int remove_device(struct sock *sk, struct hci_dev *hdev,
5230 void *data, u16 len)
5231{
5232 struct mgmt_cp_remove_device *cp = data;
5233 int err;
5234
5235 BT_DBG("%s", hdev->name);
5236
5237 hci_dev_lock(hdev);
5238
5239 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005240 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005241 u8 addr_type;
5242
5243 if (!bdaddr_type_is_le(cp->addr.type)) {
5244 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5245 MGMT_STATUS_INVALID_PARAMS,
5246 &cp->addr, sizeof(cp->addr));
5247 goto unlock;
5248 }
5249
5250 if (cp->addr.type == BDADDR_LE_PUBLIC)
5251 addr_type = ADDR_LE_DEV_PUBLIC;
5252 else
5253 addr_type = ADDR_LE_DEV_RANDOM;
5254
Johan Hedbergc71593d2014-07-02 17:37:28 +03005255 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5256 addr_type);
5257 if (!params) {
5258 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5259 MGMT_STATUS_INVALID_PARAMS,
5260 &cp->addr, sizeof(cp->addr));
5261 goto unlock;
5262 }
5263
5264 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
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
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005271 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005272 list_del(&params->list);
5273 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005274 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005275
5276 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005277 } else {
5278 if (cp->addr.type) {
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
Johan Hedbergc71593d2014-07-02 17:37:28 +03005285 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005286 }
5287
5288 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5289 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5290
5291unlock:
5292 hci_dev_unlock(hdev);
5293 return err;
5294}
5295
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005296static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5297 u16 len)
5298{
5299 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005300 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5301 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005302 u16 param_count, expected_len;
5303 int i;
5304
5305 if (!lmp_le_capable(hdev))
5306 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5307 MGMT_STATUS_NOT_SUPPORTED);
5308
5309 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005310 if (param_count > max_param_count) {
5311 BT_ERR("load_conn_param: too big param_count value %u",
5312 param_count);
5313 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5314 MGMT_STATUS_INVALID_PARAMS);
5315 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005316
5317 expected_len = sizeof(*cp) + param_count *
5318 sizeof(struct mgmt_conn_param);
5319 if (expected_len != len) {
5320 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5321 expected_len, len);
5322 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5323 MGMT_STATUS_INVALID_PARAMS);
5324 }
5325
5326 BT_DBG("%s param_count %u", hdev->name, param_count);
5327
5328 hci_dev_lock(hdev);
5329
5330 hci_conn_params_clear_disabled(hdev);
5331
5332 for (i = 0; i < param_count; i++) {
5333 struct mgmt_conn_param *param = &cp->params[i];
5334 struct hci_conn_params *hci_param;
5335 u16 min, max, latency, timeout;
5336 u8 addr_type;
5337
5338 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5339 param->addr.type);
5340
5341 if (param->addr.type == BDADDR_LE_PUBLIC) {
5342 addr_type = ADDR_LE_DEV_PUBLIC;
5343 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5344 addr_type = ADDR_LE_DEV_RANDOM;
5345 } else {
5346 BT_ERR("Ignoring invalid connection parameters");
5347 continue;
5348 }
5349
5350 min = le16_to_cpu(param->min_interval);
5351 max = le16_to_cpu(param->max_interval);
5352 latency = le16_to_cpu(param->latency);
5353 timeout = le16_to_cpu(param->timeout);
5354
5355 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5356 min, max, latency, timeout);
5357
5358 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5359 BT_ERR("Ignoring invalid connection parameters");
5360 continue;
5361 }
5362
5363 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5364 addr_type);
5365 if (!hci_param) {
5366 BT_ERR("Failed to add connection parameters");
5367 continue;
5368 }
5369
5370 hci_param->conn_min_interval = min;
5371 hci_param->conn_max_interval = max;
5372 hci_param->conn_latency = latency;
5373 hci_param->supervision_timeout = timeout;
5374 }
5375
5376 hci_dev_unlock(hdev);
5377
5378 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5379}
5380
Marcel Holtmanndbece372014-07-04 18:11:55 +02005381static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5382 void *data, u16 len)
5383{
5384 struct mgmt_cp_set_external_config *cp = data;
5385 bool changed;
5386 int err;
5387
5388 BT_DBG("%s", hdev->name);
5389
5390 if (hdev_is_powered(hdev))
5391 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5392 MGMT_STATUS_REJECTED);
5393
5394 if (cp->config != 0x00 && cp->config != 0x01)
5395 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5396 MGMT_STATUS_INVALID_PARAMS);
5397
5398 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5399 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5400 MGMT_STATUS_NOT_SUPPORTED);
5401
5402 hci_dev_lock(hdev);
5403
5404 if (cp->config)
5405 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5406 &hdev->dev_flags);
5407 else
5408 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5409 &hdev->dev_flags);
5410
5411 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5412 if (err < 0)
5413 goto unlock;
5414
5415 if (!changed)
5416 goto unlock;
5417
5418 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5419 mgmt_index_removed(hdev);
5420 change_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5421 mgmt_index_added(hdev);
5422 }
5423
5424unlock:
5425 hci_dev_unlock(hdev);
5426 return err;
5427}
5428
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005429static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005430 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5431 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005432 bool var_len;
5433 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005434} mgmt_handlers[] = {
5435 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005436 { read_version, false, MGMT_READ_VERSION_SIZE },
5437 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5438 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5439 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5440 { set_powered, false, MGMT_SETTING_SIZE },
5441 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5442 { set_connectable, false, MGMT_SETTING_SIZE },
5443 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5444 { set_pairable, false, MGMT_SETTING_SIZE },
5445 { set_link_security, false, MGMT_SETTING_SIZE },
5446 { set_ssp, false, MGMT_SETTING_SIZE },
5447 { set_hs, false, MGMT_SETTING_SIZE },
5448 { set_le, false, MGMT_SETTING_SIZE },
5449 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5450 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5451 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5452 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5453 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5454 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5455 { disconnect, false, MGMT_DISCONNECT_SIZE },
5456 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5457 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5458 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5459 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5460 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5461 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5462 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5463 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5464 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5465 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5466 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5467 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005468 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005469 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5470 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5471 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5472 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5473 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5474 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005475 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005476 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005477 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005478 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005479 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005480 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005481 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005482 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005483 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005484 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005485 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005486 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5487 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005488 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5489 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005490 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005491 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005492};
5493
Johan Hedberg03811012010-12-08 00:21:06 +02005494int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5495{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005496 void *buf;
5497 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005498 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005499 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005500 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005501 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005502 int err;
5503
5504 BT_DBG("got %zu bytes", msglen);
5505
5506 if (msglen < sizeof(*hdr))
5507 return -EINVAL;
5508
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005509 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005510 if (!buf)
5511 return -ENOMEM;
5512
5513 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5514 err = -EFAULT;
5515 goto done;
5516 }
5517
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005518 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005519 opcode = __le16_to_cpu(hdr->opcode);
5520 index = __le16_to_cpu(hdr->index);
5521 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005522
5523 if (len != msglen - sizeof(*hdr)) {
5524 err = -EINVAL;
5525 goto done;
5526 }
5527
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005528 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005529 hdev = hci_dev_get(index);
5530 if (!hdev) {
5531 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005532 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005533 goto done;
5534 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005535
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005536 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005537 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005538 err = cmd_status(sk, index, opcode,
5539 MGMT_STATUS_INVALID_INDEX);
5540 goto done;
5541 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005542
5543 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005544 opcode != MGMT_OP_READ_CONFIG_INFO &&
5545 opcode != MGMT_OP_SET_EXTERNAL_CONFIG) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005546 err = cmd_status(sk, index, opcode,
5547 MGMT_STATUS_INVALID_INDEX);
5548 goto done;
5549 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005550 }
5551
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005552 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005553 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005554 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005555 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005556 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005557 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005558 }
5559
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005560 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5561 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5562 err = cmd_status(sk, index, opcode,
5563 MGMT_STATUS_INVALID_INDEX);
5564 goto done;
5565 }
5566
5567 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5568 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005569 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005570 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005571 goto done;
5572 }
5573
Johan Hedbergbe22b542012-03-01 22:24:41 +02005574 handler = &mgmt_handlers[opcode];
5575
5576 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005577 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005578 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005579 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005580 goto done;
5581 }
5582
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005583 if (hdev)
5584 mgmt_init_hdev(sk, hdev);
5585
5586 cp = buf + sizeof(*hdr);
5587
Johan Hedbergbe22b542012-03-01 22:24:41 +02005588 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005589 if (err < 0)
5590 goto done;
5591
Johan Hedberg03811012010-12-08 00:21:06 +02005592 err = msglen;
5593
5594done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005595 if (hdev)
5596 hci_dev_put(hdev);
5597
Johan Hedberg03811012010-12-08 00:21:06 +02005598 kfree(buf);
5599 return err;
5600}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005601
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005602void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005603{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005604 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005605 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005606
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005607 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5608 return;
5609
5610 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5611 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5612 else
5613 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005614}
5615
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005616void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005617{
Johan Hedberg5f159032012-03-02 03:13:19 +02005618 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005619
Marcel Holtmann1514b892013-10-06 08:25:01 -07005620 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005621 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005622
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005623 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5624 return;
5625
Johan Hedberg744cf192011-11-08 20:40:14 +02005626 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005627
Marcel Holtmannedd38962014-07-02 21:30:55 +02005628 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5629 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5630 else
5631 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005632}
5633
Andre Guedes6046dc32014-02-26 20:21:51 -03005634/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005635static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005636{
5637 struct hci_conn_params *p;
5638
5639 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005640 /* Needed for AUTO_OFF case where might not "really"
5641 * have been powered off.
5642 */
5643 list_del_init(&p->action);
5644
5645 switch (p->auto_connect) {
5646 case HCI_AUTO_CONN_ALWAYS:
5647 list_add(&p->action, &hdev->pend_le_conns);
5648 break;
5649 case HCI_AUTO_CONN_REPORT:
5650 list_add(&p->action, &hdev->pend_le_reports);
5651 break;
5652 default:
5653 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005654 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005655 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005656
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005657 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005658}
5659
Johan Hedberg229ab392013-03-15 17:06:53 -05005660static void powered_complete(struct hci_dev *hdev, u8 status)
5661{
5662 struct cmd_lookup match = { NULL, hdev };
5663
5664 BT_DBG("status 0x%02x", status);
5665
5666 hci_dev_lock(hdev);
5667
Johan Hedbergd7347f32014-07-04 12:37:23 +03005668 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005669
Johan Hedberg229ab392013-03-15 17:06:53 -05005670 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5671
5672 new_settings(hdev, match.sk);
5673
5674 hci_dev_unlock(hdev);
5675
5676 if (match.sk)
5677 sock_put(match.sk);
5678}
5679
Johan Hedberg70da6242013-03-15 17:06:51 -05005680static int powered_update_hci(struct hci_dev *hdev)
5681{
Johan Hedberg890ea892013-03-15 17:06:52 -05005682 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005683 u8 link_sec;
5684
Johan Hedberg890ea892013-03-15 17:06:52 -05005685 hci_req_init(&req, hdev);
5686
Johan Hedberg70da6242013-03-15 17:06:51 -05005687 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5688 !lmp_host_ssp_capable(hdev)) {
5689 u8 ssp = 1;
5690
Johan Hedberg890ea892013-03-15 17:06:52 -05005691 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005692 }
5693
Johan Hedbergc73eee92013-04-19 18:35:21 +03005694 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5695 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005696 struct hci_cp_write_le_host_supported cp;
5697
5698 cp.le = 1;
5699 cp.simul = lmp_le_br_capable(hdev);
5700
5701 /* Check first if we already have the right
5702 * host state (host features set)
5703 */
5704 if (cp.le != lmp_host_le_capable(hdev) ||
5705 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005706 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5707 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005708 }
5709
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005710 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005711 /* Make sure the controller has a good default for
5712 * advertising data. This also applies to the case
5713 * where BR/EDR was toggled during the AUTO_OFF phase.
5714 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005715 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005716 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005717 update_scan_rsp_data(&req);
5718 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005719
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005720 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5721 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005722 }
5723
Johan Hedberg70da6242013-03-15 17:06:51 -05005724 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5725 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005726 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5727 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005728
5729 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005730 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5731 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005732 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005733 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005734 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005735 }
5736
Johan Hedberg229ab392013-03-15 17:06:53 -05005737 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005738}
5739
Johan Hedberg744cf192011-11-08 20:40:14 +02005740int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005741{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005742 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005743 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5744 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005745 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005746
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005747 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5748 return 0;
5749
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005750 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005751 if (powered_update_hci(hdev) == 0)
5752 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005753
Johan Hedberg229ab392013-03-15 17:06:53 -05005754 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5755 &match);
5756 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005757 }
5758
Johan Hedberg229ab392013-03-15 17:06:53 -05005759 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5760 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5761
5762 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5763 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5764 zero_cod, sizeof(zero_cod), NULL);
5765
5766new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005767 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005768
5769 if (match.sk)
5770 sock_put(match.sk);
5771
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005772 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005773}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005774
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005775void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005776{
5777 struct pending_cmd *cmd;
5778 u8 status;
5779
5780 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5781 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005782 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005783
5784 if (err == -ERFKILL)
5785 status = MGMT_STATUS_RFKILLED;
5786 else
5787 status = MGMT_STATUS_FAILED;
5788
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005789 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005790
5791 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005792}
5793
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005794void mgmt_discoverable_timeout(struct hci_dev *hdev)
5795{
5796 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005797
5798 hci_dev_lock(hdev);
5799
5800 /* When discoverable timeout triggers, then just make sure
5801 * the limited discoverable flag is cleared. Even in the case
5802 * of a timeout triggered from general discoverable, it is
5803 * safe to unconditionally clear the flag.
5804 */
5805 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005806 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005807
5808 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005809 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5810 u8 scan = SCAN_PAGE;
5811 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5812 sizeof(scan), &scan);
5813 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005814 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005815 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005816 hci_req_run(&req, NULL);
5817
5818 hdev->discov_timeout = 0;
5819
Johan Hedberg9a43e252013-10-20 19:00:07 +03005820 new_settings(hdev, NULL);
5821
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005822 hci_dev_unlock(hdev);
5823}
5824
Marcel Holtmann86a75642013-10-15 06:33:54 -07005825void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005826{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005827 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005828
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005829 /* Nothing needed here if there's a pending command since that
5830 * commands request completion callback takes care of everything
5831 * necessary.
5832 */
5833 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005834 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005835
Johan Hedbergbd107992014-02-24 14:52:19 +02005836 /* Powering off may clear the scan mode - don't let that interfere */
5837 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5838 return;
5839
Johan Hedberg9a43e252013-10-20 19:00:07 +03005840 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005841 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005842 } else {
5843 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005844 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005845 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005846
Johan Hedberg9a43e252013-10-20 19:00:07 +03005847 if (changed) {
5848 struct hci_request req;
5849
5850 /* In case this change in discoverable was triggered by
5851 * a disabling of connectable there could be a need to
5852 * update the advertising flags.
5853 */
5854 hci_req_init(&req, hdev);
5855 update_adv_data(&req);
5856 hci_req_run(&req, NULL);
5857
Marcel Holtmann86a75642013-10-15 06:33:54 -07005858 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005859 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005860}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005861
Marcel Holtmanna3309162013-10-15 06:33:55 -07005862void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005863{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005864 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005865
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005866 /* Nothing needed here if there's a pending command since that
5867 * commands request completion callback takes care of everything
5868 * necessary.
5869 */
5870 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005871 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005872
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005873 /* Powering off may clear the scan mode - don't let that interfere */
5874 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5875 return;
5876
Marcel Holtmanna3309162013-10-15 06:33:55 -07005877 if (connectable)
5878 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5879 else
5880 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005881
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005882 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005883 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005884}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005885
Johan Hedberg778b2352014-02-24 14:52:17 +02005886void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5887{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005888 /* Powering off may stop advertising - don't let that interfere */
5889 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5890 return;
5891
Johan Hedberg778b2352014-02-24 14:52:17 +02005892 if (advertising)
5893 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5894 else
5895 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5896}
5897
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005898void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005899{
Johan Hedbergca69b792011-11-11 18:10:00 +02005900 u8 mgmt_err = mgmt_status(status);
5901
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005902 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005903 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005904 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005905
5906 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005907 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005908 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005909}
5910
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005911void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5912 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005913{
Johan Hedberg86742e12011-11-07 23:13:38 +02005914 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005915
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005916 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005917
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005918 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005919 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005920 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005921 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005922 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005923 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005924
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005925 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005926}
Johan Hedbergf7520542011-01-20 12:34:39 +02005927
Johan Hedbergd7b25452014-05-23 13:19:53 +03005928static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5929{
5930 if (ltk->authenticated)
5931 return MGMT_LTK_AUTHENTICATED;
5932
5933 return MGMT_LTK_UNAUTHENTICATED;
5934}
5935
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005936void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005937{
5938 struct mgmt_ev_new_long_term_key ev;
5939
5940 memset(&ev, 0, sizeof(ev));
5941
Marcel Holtmann5192d302014-02-19 17:11:58 -08005942 /* Devices using resolvable or non-resolvable random addresses
5943 * without providing an indentity resolving key don't require
5944 * to store long term keys. Their addresses will change the
5945 * next time around.
5946 *
5947 * Only when a remote device provides an identity address
5948 * make sure the long term key is stored. If the remote
5949 * identity is known, the long term keys are internally
5950 * mapped to the identity address. So allow static random
5951 * and public addresses here.
5952 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005953 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5954 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5955 ev.store_hint = 0x00;
5956 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005957 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005958
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005959 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005960 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005961 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005962 ev.key.enc_size = key->enc_size;
5963 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005964 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005965
Johan Hedberg2ceba532014-06-16 19:25:16 +03005966 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005967 ev.key.master = 1;
5968
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005969 memcpy(ev.key.val, key->val, sizeof(key->val));
5970
Marcel Holtmann083368f2013-10-15 14:26:29 -07005971 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005972}
5973
Johan Hedberg95fbac82014-02-19 15:18:31 +02005974void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5975{
5976 struct mgmt_ev_new_irk ev;
5977
5978 memset(&ev, 0, sizeof(ev));
5979
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005980 /* For identity resolving keys from devices that are already
5981 * using a public address or static random address, do not
5982 * ask for storing this key. The identity resolving key really
5983 * is only mandatory for devices using resovlable random
5984 * addresses.
5985 *
5986 * Storing all identity resolving keys has the downside that
5987 * they will be also loaded on next boot of they system. More
5988 * identity resolving keys, means more time during scanning is
5989 * needed to actually resolve these addresses.
5990 */
5991 if (bacmp(&irk->rpa, BDADDR_ANY))
5992 ev.store_hint = 0x01;
5993 else
5994 ev.store_hint = 0x00;
5995
Johan Hedberg95fbac82014-02-19 15:18:31 +02005996 bacpy(&ev.rpa, &irk->rpa);
5997 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5998 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5999 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6000
6001 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6002}
6003
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006004void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6005 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006006{
6007 struct mgmt_ev_new_csrk ev;
6008
6009 memset(&ev, 0, sizeof(ev));
6010
6011 /* Devices using resolvable or non-resolvable random addresses
6012 * without providing an indentity resolving key don't require
6013 * to store signature resolving keys. Their addresses will change
6014 * the next time around.
6015 *
6016 * Only when a remote device provides an identity address
6017 * make sure the signature resolving key is stored. So allow
6018 * static random and public addresses here.
6019 */
6020 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6021 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6022 ev.store_hint = 0x00;
6023 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006024 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006025
6026 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6027 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6028 ev.key.master = csrk->master;
6029 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6030
6031 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6032}
6033
Andre Guedesffb5a8272014-07-01 18:10:11 -03006034void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006035 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6036 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006037{
6038 struct mgmt_ev_new_conn_param ev;
6039
Johan Hedbergc103aea2014-07-02 17:37:34 +03006040 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6041 return;
6042
Andre Guedesffb5a8272014-07-01 18:10:11 -03006043 memset(&ev, 0, sizeof(ev));
6044 bacpy(&ev.addr.bdaddr, bdaddr);
6045 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006046 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006047 ev.min_interval = cpu_to_le16(min_interval);
6048 ev.max_interval = cpu_to_le16(max_interval);
6049 ev.latency = cpu_to_le16(latency);
6050 ev.timeout = cpu_to_le16(timeout);
6051
6052 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6053}
6054
Marcel Holtmann94933992013-10-15 10:26:39 -07006055static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6056 u8 data_len)
6057{
6058 eir[eir_len++] = sizeof(type) + data_len;
6059 eir[eir_len++] = type;
6060 memcpy(&eir[eir_len], data, data_len);
6061 eir_len += data_len;
6062
6063 return eir_len;
6064}
6065
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006066void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6067 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6068 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006069{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006070 char buf[512];
6071 struct mgmt_ev_device_connected *ev = (void *) buf;
6072 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006073
Johan Hedbergb644ba32012-01-17 21:48:47 +02006074 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006075 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006076
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006077 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006078
Johan Hedbergb644ba32012-01-17 21:48:47 +02006079 if (name_len > 0)
6080 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006081 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006082
6083 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006084 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006085 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006086
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006087 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006088
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006089 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6090 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006091}
6092
Johan Hedberg8962ee72011-01-20 12:40:27 +02006093static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6094{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006095 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006096 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006097 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006098
Johan Hedberg88c3df12012-02-09 14:27:38 +02006099 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6100 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006101
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006102 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006103 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006104
6105 *sk = cmd->sk;
6106 sock_hold(*sk);
6107
Johan Hedberga664b5b2011-02-19 12:06:02 -03006108 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006109}
6110
Johan Hedberg124f6e32012-02-09 13:50:12 +02006111static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006112{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006113 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006114 struct mgmt_cp_unpair_device *cp = cmd->param;
6115 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006116
6117 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006118 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6119 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006120
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006121 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6122
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006123 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006124
6125 mgmt_pending_remove(cmd);
6126}
6127
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006128void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006129 u8 link_type, u8 addr_type, u8 reason,
6130 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006131{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006132 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006133 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006134 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006135
Johan Hedberg8b064a32014-02-24 14:52:22 +02006136 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6137 if (power_off) {
6138 struct mgmt_mode *cp = power_off->param;
6139
6140 /* The connection is still in hci_conn_hash so test for 1
6141 * instead of 0 to know if this is the last one.
6142 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006143 if (!cp->val && hci_conn_count(hdev) == 1) {
6144 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006145 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006146 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006147 }
6148
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006149 if (!mgmt_connected)
6150 return;
6151
Andre Guedes57eb7762013-10-30 19:01:41 -03006152 if (link_type != ACL_LINK && link_type != LE_LINK)
6153 return;
6154
Johan Hedberg744cf192011-11-08 20:40:14 +02006155 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006156
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006157 bacpy(&ev.addr.bdaddr, bdaddr);
6158 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6159 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006160
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006161 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006162
6163 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006164 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006165
Johan Hedberg124f6e32012-02-09 13:50:12 +02006166 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006167 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006168}
6169
Marcel Holtmann78929242013-10-06 23:55:47 -07006170void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6171 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006172{
Andre Guedes3655bba2013-10-30 19:01:40 -03006173 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6174 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006175 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006176 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006177
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006178 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6179 hdev);
6180
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006181 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006182 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006183 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006184
Andre Guedes3655bba2013-10-30 19:01:40 -03006185 cp = cmd->param;
6186
6187 if (bacmp(bdaddr, &cp->addr.bdaddr))
6188 return;
6189
6190 if (cp->addr.type != bdaddr_type)
6191 return;
6192
Johan Hedberg88c3df12012-02-09 14:27:38 +02006193 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006194 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006195
Marcel Holtmann78929242013-10-06 23:55:47 -07006196 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6197 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006198
Johan Hedberga664b5b2011-02-19 12:06:02 -03006199 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006200}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006201
Marcel Holtmann445608d2013-10-06 23:55:48 -07006202void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6203 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006204{
6205 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006206 struct pending_cmd *power_off;
6207
6208 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6209 if (power_off) {
6210 struct mgmt_mode *cp = power_off->param;
6211
6212 /* The connection is still in hci_conn_hash so test for 1
6213 * instead of 0 to know if this is the last one.
6214 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006215 if (!cp->val && hci_conn_count(hdev) == 1) {
6216 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006217 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006218 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006219 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006220
Johan Hedberg4c659c32011-11-07 23:13:39 +02006221 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006222 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006223 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006224
Marcel Holtmann445608d2013-10-06 23:55:48 -07006225 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006226}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006227
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006228void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006229{
6230 struct mgmt_ev_pin_code_request ev;
6231
Johan Hedbergd8457692012-02-17 14:24:57 +02006232 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006233 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006234 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006235
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006236 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006237}
6238
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006239void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6240 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006241{
6242 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006243 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006244
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006245 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006246 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006247 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006248
Johan Hedbergd8457692012-02-17 14:24:57 +02006249 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006250 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006251
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006252 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6253 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006254
Johan Hedberga664b5b2011-02-19 12:06:02 -03006255 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006256}
6257
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006258void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6259 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006260{
6261 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006262 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006263
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006264 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006265 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006266 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006267
Johan Hedbergd8457692012-02-17 14:24:57 +02006268 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006269 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006270
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006271 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6272 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006273
Johan Hedberga664b5b2011-02-19 12:06:02 -03006274 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006275}
Johan Hedberga5c29682011-02-19 12:05:57 -03006276
Johan Hedberg744cf192011-11-08 20:40:14 +02006277int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006278 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006279 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006280{
6281 struct mgmt_ev_user_confirm_request ev;
6282
Johan Hedberg744cf192011-11-08 20:40:14 +02006283 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006284
Johan Hedberg272d90d2012-02-09 15:26:12 +02006285 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006286 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006287 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006288 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006289
Johan Hedberg744cf192011-11-08 20:40:14 +02006290 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006291 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006292}
6293
Johan Hedberg272d90d2012-02-09 15:26:12 +02006294int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006295 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006296{
6297 struct mgmt_ev_user_passkey_request ev;
6298
6299 BT_DBG("%s", hdev->name);
6300
Johan Hedberg272d90d2012-02-09 15:26:12 +02006301 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006302 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006303
6304 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006305 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006306}
6307
Brian Gix0df4c182011-11-16 13:53:13 -08006308static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006309 u8 link_type, u8 addr_type, u8 status,
6310 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006311{
6312 struct pending_cmd *cmd;
6313 struct mgmt_rp_user_confirm_reply rp;
6314 int err;
6315
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006316 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006317 if (!cmd)
6318 return -ENOENT;
6319
Johan Hedberg272d90d2012-02-09 15:26:12 +02006320 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006321 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006322 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006323 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006324
Johan Hedberga664b5b2011-02-19 12:06:02 -03006325 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006326
6327 return err;
6328}
6329
Johan Hedberg744cf192011-11-08 20:40:14 +02006330int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006331 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006332{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006333 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006334 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006335}
6336
Johan Hedberg272d90d2012-02-09 15:26:12 +02006337int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006338 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006339{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006340 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006341 status,
6342 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006343}
Johan Hedberg2a611692011-02-19 12:06:00 -03006344
Brian Gix604086b2011-11-23 08:28:33 -08006345int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006346 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006347{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006348 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006349 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006350}
6351
Johan Hedberg272d90d2012-02-09 15:26:12 +02006352int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006353 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006354{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006355 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006356 status,
6357 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006358}
6359
Johan Hedberg92a25252012-09-06 18:39:26 +03006360int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6361 u8 link_type, u8 addr_type, u32 passkey,
6362 u8 entered)
6363{
6364 struct mgmt_ev_passkey_notify ev;
6365
6366 BT_DBG("%s", hdev->name);
6367
6368 bacpy(&ev.addr.bdaddr, bdaddr);
6369 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6370 ev.passkey = __cpu_to_le32(passkey);
6371 ev.entered = entered;
6372
6373 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6374}
6375
Marcel Holtmanne5460992013-10-15 14:26:23 -07006376void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6377 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006378{
6379 struct mgmt_ev_auth_failed ev;
6380
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006381 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006382 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006383 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006384
Marcel Holtmanne5460992013-10-15 14:26:23 -07006385 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006386}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006387
Marcel Holtmann464996a2013-10-15 14:26:24 -07006388void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006389{
6390 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006391 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006392
6393 if (status) {
6394 u8 mgmt_err = mgmt_status(status);
6395 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006396 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006397 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006398 }
6399
Marcel Holtmann464996a2013-10-15 14:26:24 -07006400 if (test_bit(HCI_AUTH, &hdev->flags))
6401 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6402 &hdev->dev_flags);
6403 else
6404 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6405 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006406
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006407 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006408 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006409
Johan Hedberg47990ea2012-02-22 11:58:37 +02006410 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006411 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006412
6413 if (match.sk)
6414 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006415}
6416
Johan Hedberg890ea892013-03-15 17:06:52 -05006417static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006418{
Johan Hedberg890ea892013-03-15 17:06:52 -05006419 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006420 struct hci_cp_write_eir cp;
6421
Johan Hedberg976eb202012-10-24 21:12:01 +03006422 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006423 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006424
Johan Hedbergc80da272012-02-22 15:38:48 +02006425 memset(hdev->eir, 0, sizeof(hdev->eir));
6426
Johan Hedbergcacaf522012-02-21 00:52:42 +02006427 memset(&cp, 0, sizeof(cp));
6428
Johan Hedberg890ea892013-03-15 17:06:52 -05006429 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006430}
6431
Marcel Holtmann3e248562013-10-15 14:26:25 -07006432void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006433{
6434 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006435 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006436 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006437
6438 if (status) {
6439 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006440
6441 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006442 &hdev->dev_flags)) {
6443 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006444 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006445 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006446
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006447 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6448 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006449 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006450 }
6451
6452 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006453 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006454 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006455 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6456 if (!changed)
6457 changed = test_and_clear_bit(HCI_HS_ENABLED,
6458 &hdev->dev_flags);
6459 else
6460 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006461 }
6462
6463 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6464
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006465 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006466 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006467
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006468 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006469 sock_put(match.sk);
6470
Johan Hedberg890ea892013-03-15 17:06:52 -05006471 hci_req_init(&req, hdev);
6472
Johan Hedberg37699722014-06-24 14:00:27 +03006473 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6474 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6475 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6476 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006477 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006478 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006479 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006480 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006481
6482 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006483}
6484
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006485void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6486{
6487 struct cmd_lookup match = { NULL, hdev };
6488 bool changed = false;
6489
6490 if (status) {
6491 u8 mgmt_err = mgmt_status(status);
6492
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006493 if (enable) {
6494 if (test_and_clear_bit(HCI_SC_ENABLED,
6495 &hdev->dev_flags))
6496 new_settings(hdev, NULL);
6497 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6498 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006499
6500 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6501 cmd_status_rsp, &mgmt_err);
6502 return;
6503 }
6504
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006505 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006506 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006507 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006508 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006509 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6510 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006511
6512 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6513 settings_rsp, &match);
6514
6515 if (changed)
6516 new_settings(hdev, match.sk);
6517
6518 if (match.sk)
6519 sock_put(match.sk);
6520}
6521
Johan Hedberg92da6092013-03-15 17:06:55 -05006522static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006523{
6524 struct cmd_lookup *match = data;
6525
Johan Hedberg90e70452012-02-23 23:09:40 +02006526 if (match->sk == NULL) {
6527 match->sk = cmd->sk;
6528 sock_hold(match->sk);
6529 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006530}
6531
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006532void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6533 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006534{
Johan Hedberg90e70452012-02-23 23:09:40 +02006535 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006536
Johan Hedberg92da6092013-03-15 17:06:55 -05006537 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6538 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6539 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006540
6541 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006542 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6543 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006544
6545 if (match.sk)
6546 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006547}
6548
Marcel Holtmann7667da32013-10-15 14:26:27 -07006549void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006550{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006551 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006552 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006553
Johan Hedberg13928972013-03-15 17:07:00 -05006554 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006555 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006556
6557 memset(&ev, 0, sizeof(ev));
6558 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006559 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006560
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006561 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006562 if (!cmd) {
6563 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006564
Johan Hedberg13928972013-03-15 17:07:00 -05006565 /* If this is a HCI command related to powering on the
6566 * HCI dev don't send any mgmt signals.
6567 */
6568 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006569 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006570 }
6571
Marcel Holtmann7667da32013-10-15 14:26:27 -07006572 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6573 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006574}
Szymon Jancc35938b2011-03-22 13:12:21 +01006575
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006576void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6577 u8 *randomizer192, u8 *hash256,
6578 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006579{
6580 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006581
Johan Hedberg744cf192011-11-08 20:40:14 +02006582 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006583
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006584 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006585 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006586 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006587
6588 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006589 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6590 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006591 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006592 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6593 hash256 && randomizer256) {
6594 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006595
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006596 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6597 memcpy(rp.randomizer192, randomizer192,
6598 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006599
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006600 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6601 memcpy(rp.randomizer256, randomizer256,
6602 sizeof(rp.randomizer256));
6603
6604 cmd_complete(cmd->sk, hdev->id,
6605 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6606 &rp, sizeof(rp));
6607 } else {
6608 struct mgmt_rp_read_local_oob_data rp;
6609
6610 memcpy(rp.hash, hash192, sizeof(rp.hash));
6611 memcpy(rp.randomizer, randomizer192,
6612 sizeof(rp.randomizer));
6613
6614 cmd_complete(cmd->sk, hdev->id,
6615 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6616 &rp, sizeof(rp));
6617 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006618 }
6619
6620 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006621}
Johan Hedberge17acd42011-03-30 23:57:16 +03006622
Marcel Holtmann901801b2013-10-06 23:55:51 -07006623void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006624 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6625 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006626{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006627 char buf[512];
6628 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006629 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006630 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006631
Johan Hedberg75ce2082014-07-02 22:42:01 +03006632 /* Don't send events for a non-kernel initiated discovery. With
6633 * LE one exception is if we have pend_le_reports > 0 in which
6634 * case we're doing passive scanning and want these events.
6635 */
6636 if (!hci_discovery_active(hdev)) {
6637 if (link_type == ACL_LINK)
6638 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006639 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006640 return;
6641 }
Andre Guedes12602d02013-04-30 15:29:40 -03006642
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006643 /* Make sure that the buffer is big enough. The 5 extra bytes
6644 * are for the potential CoD field.
6645 */
6646 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006647 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006648
Johan Hedberg1dc06092012-01-15 21:01:23 +02006649 memset(buf, 0, sizeof(buf));
6650
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006651 irk = hci_get_irk(hdev, bdaddr, addr_type);
6652 if (irk) {
6653 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6654 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6655 } else {
6656 bacpy(&ev->addr.bdaddr, bdaddr);
6657 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6658 }
6659
Johan Hedberge319d2e2012-01-15 19:51:59 +02006660 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006661 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006662
Johan Hedberg1dc06092012-01-15 21:01:23 +02006663 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006664 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006665
Johan Hedberg1dc06092012-01-15 21:01:23 +02006666 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6667 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006668 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006669
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006670 if (scan_rsp_len > 0)
6671 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6672
6673 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6674 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006675
Marcel Holtmann901801b2013-10-06 23:55:51 -07006676 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006677}
Johan Hedberga88a9652011-03-30 13:18:12 +03006678
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006679void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6680 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006681{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006682 struct mgmt_ev_device_found *ev;
6683 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6684 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006685
Johan Hedbergb644ba32012-01-17 21:48:47 +02006686 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006687
Johan Hedbergb644ba32012-01-17 21:48:47 +02006688 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006689
Johan Hedbergb644ba32012-01-17 21:48:47 +02006690 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006691 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006692 ev->rssi = rssi;
6693
6694 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006695 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006696
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006697 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006698
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006699 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006700}
Johan Hedberg314b2382011-04-27 10:29:57 -04006701
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006702void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006703{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006704 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006705 struct pending_cmd *cmd;
6706
Andre Guedes343fb142011-11-22 17:14:19 -03006707 BT_DBG("%s discovering %u", hdev->name, discovering);
6708
Johan Hedberg164a6e72011-11-01 17:06:44 +02006709 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006710 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006711 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006712 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006713
6714 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006715 u8 type = hdev->discovery.type;
6716
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006717 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6718 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006719 mgmt_pending_remove(cmd);
6720 }
6721
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006722 memset(&ev, 0, sizeof(ev));
6723 ev.type = hdev->discovery.type;
6724 ev.discovering = discovering;
6725
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006726 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006727}
Antti Julku5e762442011-08-25 16:48:02 +03006728
Marcel Holtmann5976e602013-10-06 04:08:14 -07006729static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6730{
6731 BT_DBG("%s status %u", hdev->name, status);
6732
6733 /* Clear the advertising mgmt setting if we failed to re-enable it */
6734 if (status) {
6735 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006736 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006737 }
6738}
6739
6740void mgmt_reenable_advertising(struct hci_dev *hdev)
6741{
6742 struct hci_request req;
6743
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006744 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006745 return;
6746
6747 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6748 return;
6749
6750 hci_req_init(&req, hdev);
6751 enable_advertising(&req);
6752
6753 /* If this fails we have no option but to let user space know
6754 * that we've disabled advertising.
6755 */
6756 if (hci_req_run(&req, adv_enable_complete) < 0) {
6757 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006758 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006759 }
6760}