blob: f75a090cd7e4cf4ef9f4ece4c9820405f04f6c34 [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 Holtmannb75cf9c2014-05-09 04:18:42 -070038#define MGMT_REVISION 6
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 Hedberge70bb2e2012-02-13 16:59:33 +020088};
89
90static const u16 mgmt_events[] = {
91 MGMT_EV_CONTROLLER_ERROR,
92 MGMT_EV_INDEX_ADDED,
93 MGMT_EV_INDEX_REMOVED,
94 MGMT_EV_NEW_SETTINGS,
95 MGMT_EV_CLASS_OF_DEV_CHANGED,
96 MGMT_EV_LOCAL_NAME_CHANGED,
97 MGMT_EV_NEW_LINK_KEY,
98 MGMT_EV_NEW_LONG_TERM_KEY,
99 MGMT_EV_DEVICE_CONNECTED,
100 MGMT_EV_DEVICE_DISCONNECTED,
101 MGMT_EV_CONNECT_FAILED,
102 MGMT_EV_PIN_CODE_REQUEST,
103 MGMT_EV_USER_CONFIRM_REQUEST,
104 MGMT_EV_USER_PASSKEY_REQUEST,
105 MGMT_EV_AUTH_FAILED,
106 MGMT_EV_DEVICE_FOUND,
107 MGMT_EV_DISCOVERING,
108 MGMT_EV_DEVICE_BLOCKED,
109 MGMT_EV_DEVICE_UNBLOCKED,
110 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300111 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800112 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700113 MGMT_EV_NEW_CSRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200114};
115
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800116#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200117
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200118#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
119 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
120
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200121struct pending_cmd {
122 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200123 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200124 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100125 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200126 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300127 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200128};
129
Johan Hedbergca69b792011-11-11 18:10:00 +0200130/* HCI to MGMT error code conversion table */
131static u8 mgmt_status_table[] = {
132 MGMT_STATUS_SUCCESS,
133 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
134 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
135 MGMT_STATUS_FAILED, /* Hardware Failure */
136 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
137 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200138 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200139 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
140 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
141 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
142 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
143 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
144 MGMT_STATUS_BUSY, /* Command Disallowed */
145 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
146 MGMT_STATUS_REJECTED, /* Rejected Security */
147 MGMT_STATUS_REJECTED, /* Rejected Personal */
148 MGMT_STATUS_TIMEOUT, /* Host Timeout */
149 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
150 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
151 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
152 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
153 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
154 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
155 MGMT_STATUS_BUSY, /* Repeated Attempts */
156 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
157 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
158 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
159 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
160 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
161 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
162 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
163 MGMT_STATUS_FAILED, /* Unspecified Error */
164 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
165 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
166 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
167 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
168 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
169 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
170 MGMT_STATUS_FAILED, /* Unit Link Key Used */
171 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
172 MGMT_STATUS_TIMEOUT, /* Instant Passed */
173 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
174 MGMT_STATUS_FAILED, /* Transaction Collision */
175 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
176 MGMT_STATUS_REJECTED, /* QoS Rejected */
177 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
178 MGMT_STATUS_REJECTED, /* Insufficient Security */
179 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
180 MGMT_STATUS_BUSY, /* Role Switch Pending */
181 MGMT_STATUS_FAILED, /* Slot Violation */
182 MGMT_STATUS_FAILED, /* Role Switch Failed */
183 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
184 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
185 MGMT_STATUS_BUSY, /* Host Busy Pairing */
186 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
187 MGMT_STATUS_BUSY, /* Controller Busy */
188 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
189 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
190 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
191 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
192 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
193};
194
195static u8 mgmt_status(u8 hci_status)
196{
197 if (hci_status < ARRAY_SIZE(mgmt_status_table))
198 return mgmt_status_table[hci_status];
199
200 return MGMT_STATUS_FAILED;
201}
202
Szymon Janc4e51eae2011-02-25 19:05:48 +0100203static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200204{
205 struct sk_buff *skb;
206 struct mgmt_hdr *hdr;
207 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300208 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200209
Szymon Janc34eb5252011-02-28 14:10:08 +0100210 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200211
Andre Guedes790eff42012-06-07 19:05:46 -0300212 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200213 if (!skb)
214 return -ENOMEM;
215
216 hdr = (void *) skb_put(skb, sizeof(*hdr));
217
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700218 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100219 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200220 hdr->len = cpu_to_le16(sizeof(*ev));
221
222 ev = (void *) skb_put(skb, sizeof(*ev));
223 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200224 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200225
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300226 err = sock_queue_rcv_skb(sk, skb);
227 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200228 kfree_skb(skb);
229
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300230 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200231}
232
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200233static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300234 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200235{
236 struct sk_buff *skb;
237 struct mgmt_hdr *hdr;
238 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300239 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200240
241 BT_DBG("sock %p", sk);
242
Andre Guedes790eff42012-06-07 19:05:46 -0300243 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200244 if (!skb)
245 return -ENOMEM;
246
247 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200248
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700249 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100250 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200251 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200252
Johan Hedberga38528f2011-01-22 06:46:43 +0200253 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200254 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200255 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100256
257 if (rp)
258 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200259
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300260 err = sock_queue_rcv_skb(sk, skb);
261 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200262 kfree_skb(skb);
263
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100264 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200265}
266
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300267static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
268 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200269{
270 struct mgmt_rp_read_version rp;
271
272 BT_DBG("sock %p", sk);
273
274 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200279}
280
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300281static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
282 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200283{
284 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200285 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
286 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200287 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200288 size_t rp_size;
289 int i, err;
290
291 BT_DBG("sock %p", sk);
292
293 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
294
295 rp = kmalloc(rp_size, GFP_KERNEL);
296 if (!rp)
297 return -ENOMEM;
298
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700299 rp->num_commands = cpu_to_le16(num_commands);
300 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200301
302 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
303 put_unaligned_le16(mgmt_commands[i], opcode);
304
305 for (i = 0; i < num_events; i++, opcode++)
306 put_unaligned_le16(mgmt_events[i], opcode);
307
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200308 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300309 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200310 kfree(rp);
311
312 return err;
313}
314
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300315static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
316 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200317{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200318 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200319 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200320 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200321 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300322 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200323
324 BT_DBG("sock %p", sk);
325
326 read_lock(&hci_dev_list_lock);
327
328 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300329 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700330 if (d->dev_type == HCI_BREDR)
331 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200332 }
333
Johan Hedberga38528f2011-01-22 06:46:43 +0200334 rp_len = sizeof(*rp) + (2 * count);
335 rp = kmalloc(rp_len, GFP_ATOMIC);
336 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100337 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200338 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100339 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340
Johan Hedberg476e44c2012-10-19 20:10:46 +0300341 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200342 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200343 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200344 continue;
345
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700346 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
347 continue;
348
Marcel Holtmann1514b892013-10-06 08:25:01 -0700349 if (d->dev_type == HCI_BREDR) {
350 rp->index[count++] = cpu_to_le16(d->id);
351 BT_DBG("Added hci%u", d->id);
352 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200353 }
354
Johan Hedberg476e44c2012-10-19 20:10:46 +0300355 rp->num_controllers = cpu_to_le16(count);
356 rp_len = sizeof(*rp) + (2 * count);
357
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200358 read_unlock(&hci_dev_list_lock);
359
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200360 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300361 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362
Johan Hedberga38528f2011-01-22 06:46:43 +0200363 kfree(rp);
364
365 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366}
367
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200368static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200369{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200370 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200371
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200372 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200373 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800374 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200375
Andre Guedesed3fa312012-07-24 15:03:46 -0300376 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300377 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500378 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
379 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300380 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200381 settings |= MGMT_SETTING_BREDR;
382 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700383
384 if (lmp_ssp_capable(hdev)) {
385 settings |= MGMT_SETTING_SSP;
386 settings |= MGMT_SETTING_HS;
387 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800388
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800389 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200390 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800391 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700392 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100393
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300394 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200395 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300396 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200397 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300398 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200399
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200400 return settings;
401}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200402
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200403static u32 get_current_settings(struct hci_dev *hdev)
404{
405 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200406
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200407 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100408 settings |= MGMT_SETTING_POWERED;
409
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200410 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200411 settings |= MGMT_SETTING_CONNECTABLE;
412
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500413 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
414 settings |= MGMT_SETTING_FAST_CONNECTABLE;
415
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200416 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200417 settings |= MGMT_SETTING_DISCOVERABLE;
418
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200419 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200420 settings |= MGMT_SETTING_PAIRABLE;
421
Johan Hedberg56f87902013-10-02 13:43:13 +0300422 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200423 settings |= MGMT_SETTING_BREDR;
424
Johan Hedberg06199cf2012-02-22 16:37:11 +0200425 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200426 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200427
Johan Hedberg47990ea2012-02-22 11:58:37 +0200428 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200430
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200431 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200432 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200433
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200434 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
435 settings |= MGMT_SETTING_HS;
436
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200437 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300438 settings |= MGMT_SETTING_ADVERTISING;
439
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800440 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
441 settings |= MGMT_SETTING_SECURE_CONN;
442
Johan Hedberg0663b292014-06-24 13:15:50 +0300443 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800444 settings |= MGMT_SETTING_DEBUG_KEYS;
445
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200446 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
447 settings |= MGMT_SETTING_PRIVACY;
448
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200449 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200450}
451
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300452#define PNP_INFO_SVCLASS_ID 0x1200
453
Johan Hedberg213202e2013-01-27 00:31:33 +0200454static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
455{
456 u8 *ptr = data, *uuids_start = NULL;
457 struct bt_uuid *uuid;
458
459 if (len < 4)
460 return ptr;
461
462 list_for_each_entry(uuid, &hdev->uuids, list) {
463 u16 uuid16;
464
465 if (uuid->size != 16)
466 continue;
467
468 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
469 if (uuid16 < 0x1100)
470 continue;
471
472 if (uuid16 == PNP_INFO_SVCLASS_ID)
473 continue;
474
475 if (!uuids_start) {
476 uuids_start = ptr;
477 uuids_start[0] = 1;
478 uuids_start[1] = EIR_UUID16_ALL;
479 ptr += 2;
480 }
481
482 /* Stop if not enough space to put next UUID */
483 if ((ptr - data) + sizeof(u16) > len) {
484 uuids_start[1] = EIR_UUID16_SOME;
485 break;
486 }
487
488 *ptr++ = (uuid16 & 0x00ff);
489 *ptr++ = (uuid16 & 0xff00) >> 8;
490 uuids_start[0] += sizeof(uuid16);
491 }
492
493 return ptr;
494}
495
Johan Hedbergcdf19632013-01-27 00:31:34 +0200496static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
497{
498 u8 *ptr = data, *uuids_start = NULL;
499 struct bt_uuid *uuid;
500
501 if (len < 6)
502 return ptr;
503
504 list_for_each_entry(uuid, &hdev->uuids, list) {
505 if (uuid->size != 32)
506 continue;
507
508 if (!uuids_start) {
509 uuids_start = ptr;
510 uuids_start[0] = 1;
511 uuids_start[1] = EIR_UUID32_ALL;
512 ptr += 2;
513 }
514
515 /* Stop if not enough space to put next UUID */
516 if ((ptr - data) + sizeof(u32) > len) {
517 uuids_start[1] = EIR_UUID32_SOME;
518 break;
519 }
520
521 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
522 ptr += sizeof(u32);
523 uuids_start[0] += sizeof(u32);
524 }
525
526 return ptr;
527}
528
Johan Hedbergc00d5752013-01-27 00:31:35 +0200529static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
530{
531 u8 *ptr = data, *uuids_start = NULL;
532 struct bt_uuid *uuid;
533
534 if (len < 18)
535 return ptr;
536
537 list_for_each_entry(uuid, &hdev->uuids, list) {
538 if (uuid->size != 128)
539 continue;
540
541 if (!uuids_start) {
542 uuids_start = ptr;
543 uuids_start[0] = 1;
544 uuids_start[1] = EIR_UUID128_ALL;
545 ptr += 2;
546 }
547
548 /* Stop if not enough space to put next UUID */
549 if ((ptr - data) + 16 > len) {
550 uuids_start[1] = EIR_UUID128_SOME;
551 break;
552 }
553
554 memcpy(ptr, uuid->uuid, 16);
555 ptr += 16;
556 uuids_start[0] += 16;
557 }
558
559 return ptr;
560}
561
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300562static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
563{
564 struct pending_cmd *cmd;
565
566 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
567 if (cmd->opcode == opcode)
568 return cmd;
569 }
570
571 return NULL;
572}
573
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700574static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
575{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700576 u8 ad_len = 0;
577 size_t name_len;
578
579 name_len = strlen(hdev->dev_name);
580 if (name_len > 0) {
581 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
582
583 if (name_len > max_len) {
584 name_len = max_len;
585 ptr[1] = EIR_NAME_SHORT;
586 } else
587 ptr[1] = EIR_NAME_COMPLETE;
588
589 ptr[0] = name_len + 1;
590
591 memcpy(ptr + 2, hdev->dev_name, name_len);
592
593 ad_len += (name_len + 2);
594 ptr += (name_len + 2);
595 }
596
597 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700598}
599
600static void update_scan_rsp_data(struct hci_request *req)
601{
602 struct hci_dev *hdev = req->hdev;
603 struct hci_cp_le_set_scan_rsp_data cp;
604 u8 len;
605
Johan Hedberg7751ef12013-10-19 23:38:15 +0300606 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700607 return;
608
609 memset(&cp, 0, sizeof(cp));
610
611 len = create_scan_rsp_data(hdev, cp.data);
612
Johan Hedbergeb438b52013-10-16 15:31:07 +0300613 if (hdev->scan_rsp_data_len == len &&
614 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700615 return;
616
Johan Hedbergeb438b52013-10-16 15:31:07 +0300617 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
618 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700619
620 cp.length = len;
621
622 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
623}
624
Johan Hedberg9a43e252013-10-20 19:00:07 +0300625static u8 get_adv_discov_flags(struct hci_dev *hdev)
626{
627 struct pending_cmd *cmd;
628
629 /* If there's a pending mgmt command the flags will not yet have
630 * their final values, so check for this first.
631 */
632 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
633 if (cmd) {
634 struct mgmt_mode *cp = cmd->param;
635 if (cp->val == 0x01)
636 return LE_AD_GENERAL;
637 else if (cp->val == 0x02)
638 return LE_AD_LIMITED;
639 } else {
640 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
641 return LE_AD_LIMITED;
642 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
643 return LE_AD_GENERAL;
644 }
645
646 return 0;
647}
648
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700649static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700650{
651 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700652
Johan Hedberg9a43e252013-10-20 19:00:07 +0300653 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700654
Johan Hedberge8340042014-01-30 11:16:50 -0800655 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700656 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700657
658 if (flags) {
659 BT_DBG("adv flags 0x%02x", flags);
660
661 ptr[0] = 2;
662 ptr[1] = EIR_FLAGS;
663 ptr[2] = flags;
664
665 ad_len += 3;
666 ptr += 3;
667 }
668
669 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
670 ptr[0] = 2;
671 ptr[1] = EIR_TX_POWER;
672 ptr[2] = (u8) hdev->adv_tx_power;
673
674 ad_len += 3;
675 ptr += 3;
676 }
677
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678 return ad_len;
679}
680
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700681static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700682{
683 struct hci_dev *hdev = req->hdev;
684 struct hci_cp_le_set_adv_data cp;
685 u8 len;
686
Johan Hedberg10994ce2013-10-19 23:38:16 +0300687 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700688 return;
689
690 memset(&cp, 0, sizeof(cp));
691
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700692 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700693
694 if (hdev->adv_data_len == len &&
695 memcmp(cp.data, hdev->adv_data, len) == 0)
696 return;
697
698 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
699 hdev->adv_data_len = len;
700
701 cp.length = len;
702
703 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
704}
705
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300706static void create_eir(struct hci_dev *hdev, u8 *data)
707{
708 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300709 size_t name_len;
710
711 name_len = strlen(hdev->dev_name);
712
713 if (name_len > 0) {
714 /* EIR Data type */
715 if (name_len > 48) {
716 name_len = 48;
717 ptr[1] = EIR_NAME_SHORT;
718 } else
719 ptr[1] = EIR_NAME_COMPLETE;
720
721 /* EIR Data length */
722 ptr[0] = name_len + 1;
723
724 memcpy(ptr + 2, hdev->dev_name, name_len);
725
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300726 ptr += (name_len + 2);
727 }
728
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100729 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700730 ptr[0] = 2;
731 ptr[1] = EIR_TX_POWER;
732 ptr[2] = (u8) hdev->inq_tx_power;
733
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700734 ptr += 3;
735 }
736
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700737 if (hdev->devid_source > 0) {
738 ptr[0] = 9;
739 ptr[1] = EIR_DEVICE_ID;
740
741 put_unaligned_le16(hdev->devid_source, ptr + 2);
742 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
743 put_unaligned_le16(hdev->devid_product, ptr + 6);
744 put_unaligned_le16(hdev->devid_version, ptr + 8);
745
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700746 ptr += 10;
747 }
748
Johan Hedberg213202e2013-01-27 00:31:33 +0200749 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200750 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200751 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300752}
753
Johan Hedberg890ea892013-03-15 17:06:52 -0500754static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300755{
Johan Hedberg890ea892013-03-15 17:06:52 -0500756 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300757 struct hci_cp_write_eir cp;
758
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200759 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500760 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200761
Johan Hedberg976eb202012-10-24 21:12:01 +0300762 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500763 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300764
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200765 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500766 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300767
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200768 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500769 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300770
771 memset(&cp, 0, sizeof(cp));
772
773 create_eir(hdev, cp.data);
774
775 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500776 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300777
778 memcpy(hdev->eir, cp.data, sizeof(cp.data));
779
Johan Hedberg890ea892013-03-15 17:06:52 -0500780 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300781}
782
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200783static u8 get_service_classes(struct hci_dev *hdev)
784{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300785 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200786 u8 val = 0;
787
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300788 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200789 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200790
791 return val;
792}
793
Johan Hedberg890ea892013-03-15 17:06:52 -0500794static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200795{
Johan Hedberg890ea892013-03-15 17:06:52 -0500796 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200797 u8 cod[3];
798
799 BT_DBG("%s", hdev->name);
800
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200801 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500802 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200803
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300804 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
805 return;
806
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200807 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500808 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200809
810 cod[0] = hdev->minor_class;
811 cod[1] = hdev->major_class;
812 cod[2] = get_service_classes(hdev);
813
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700814 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
815 cod[1] |= 0x20;
816
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500818 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200819
Johan Hedberg890ea892013-03-15 17:06:52 -0500820 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200821}
822
Johan Hedberga4858cb2014-02-25 19:56:31 +0200823static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200824{
825 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200826
827 /* If there's a pending mgmt command the flag will not yet have
828 * it's final value, so check for this first.
829 */
830 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
831 if (cmd) {
832 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200833 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200834 }
835
Johan Hedberga4858cb2014-02-25 19:56:31 +0200836 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200837}
838
839static void enable_advertising(struct hci_request *req)
840{
841 struct hci_dev *hdev = req->hdev;
842 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200843 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200844 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200845
Johan Hedberg8d972502014-02-28 12:54:14 +0200846 /* Clear the HCI_ADVERTISING bit temporarily so that the
847 * hci_update_random_address knows that it's safe to go ahead
848 * and write a new random address. The flag will be set back on
849 * as soon as the SET_ADV_ENABLE HCI command completes.
850 */
851 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
852
Johan Hedberga4858cb2014-02-25 19:56:31 +0200853 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200854
Johan Hedberga4858cb2014-02-25 19:56:31 +0200855 /* Set require_privacy to true only when non-connectable
856 * advertising is used. In that case it is fine to use a
857 * non-resolvable private address.
858 */
859 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200860 return;
861
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800862 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700863 cp.min_interval = cpu_to_le16(0x0800);
864 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200865 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200866 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200867 cp.channel_map = hdev->le_adv_channel_map;
868
869 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
870
871 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
872}
873
874static void disable_advertising(struct hci_request *req)
875{
876 u8 enable = 0x00;
877
878 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
879}
880
Johan Hedberg7d785252011-12-15 00:47:39 +0200881static void service_cache_off(struct work_struct *work)
882{
883 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300884 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500885 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200886
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200887 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200888 return;
889
Johan Hedberg890ea892013-03-15 17:06:52 -0500890 hci_req_init(&req, hdev);
891
Johan Hedberg7d785252011-12-15 00:47:39 +0200892 hci_dev_lock(hdev);
893
Johan Hedberg890ea892013-03-15 17:06:52 -0500894 update_eir(&req);
895 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200896
897 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500898
899 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200900}
901
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200902static void rpa_expired(struct work_struct *work)
903{
904 struct hci_dev *hdev = container_of(work, struct hci_dev,
905 rpa_expired.work);
906 struct hci_request req;
907
908 BT_DBG("");
909
910 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
911
912 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
913 hci_conn_num(hdev, LE_LINK) > 0)
914 return;
915
916 /* The generation of a new RPA and programming it into the
917 * controller happens in the enable_advertising() function.
918 */
919
920 hci_req_init(&req, hdev);
921
922 disable_advertising(&req);
923 enable_advertising(&req);
924
925 hci_req_run(&req, NULL);
926}
927
Johan Hedberg6a919082012-02-28 06:17:26 +0200928static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200929{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200930 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200931 return;
932
Johan Hedberg4f87da82012-03-02 19:55:56 +0200933 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200934 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200935
Johan Hedberg4f87da82012-03-02 19:55:56 +0200936 /* Non-mgmt controlled devices get this bit set
937 * implicitly so that pairing works for them, however
938 * for mgmt we require user-space to explicitly enable
939 * it
940 */
941 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200942}
943
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200944static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300945 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200946{
947 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200948
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200949 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200950
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300951 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200952
Johan Hedberg03811012010-12-08 00:21:06 +0200953 memset(&rp, 0, sizeof(rp));
954
Johan Hedberg03811012010-12-08 00:21:06 +0200955 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200956
957 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200958 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200959
960 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
961 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
962
963 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200964
965 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200966 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300968 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200969
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200970 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300971 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200972}
973
974static void mgmt_pending_free(struct pending_cmd *cmd)
975{
976 sock_put(cmd->sk);
977 kfree(cmd->param);
978 kfree(cmd);
979}
980
981static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300982 struct hci_dev *hdev, void *data,
983 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200984{
985 struct pending_cmd *cmd;
986
Andre Guedes12b94562012-06-07 19:05:45 -0300987 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200988 if (!cmd)
989 return NULL;
990
991 cmd->opcode = opcode;
992 cmd->index = hdev->id;
993
Andre Guedes12b94562012-06-07 19:05:45 -0300994 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200995 if (!cmd->param) {
996 kfree(cmd);
997 return NULL;
998 }
999
1000 if (data)
1001 memcpy(cmd->param, data, len);
1002
1003 cmd->sk = sk;
1004 sock_hold(sk);
1005
1006 list_add(&cmd->list, &hdev->mgmt_pending);
1007
1008 return cmd;
1009}
1010
1011static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001012 void (*cb)(struct pending_cmd *cmd,
1013 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001014 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001015{
Andre Guedesa3d09352013-02-01 11:21:30 -03001016 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001017
Andre Guedesa3d09352013-02-01 11:21:30 -03001018 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001019 if (opcode > 0 && cmd->opcode != opcode)
1020 continue;
1021
1022 cb(cmd, data);
1023 }
1024}
1025
Johan Hedberg03811012010-12-08 00:21:06 +02001026static void mgmt_pending_remove(struct pending_cmd *cmd)
1027{
1028 list_del(&cmd->list);
1029 mgmt_pending_free(cmd);
1030}
1031
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001032static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001033{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001034 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001035
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001036 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001037 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001038}
1039
Johan Hedberg8b064a32014-02-24 14:52:22 +02001040static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1041{
1042 BT_DBG("%s status 0x%02x", hdev->name, status);
1043
Johan Hedberga3172b72014-02-28 09:33:44 +02001044 if (hci_conn_count(hdev) == 0) {
1045 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001046 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001047 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001048}
1049
Johan Hedberg21a60d32014-06-10 14:05:58 +03001050static void hci_stop_discovery(struct hci_request *req)
1051{
1052 struct hci_dev *hdev = req->hdev;
1053 struct hci_cp_remote_name_req_cancel cp;
1054 struct inquiry_entry *e;
1055
1056 switch (hdev->discovery.state) {
1057 case DISCOVERY_FINDING:
1058 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1059 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1060 } else {
1061 cancel_delayed_work(&hdev->le_scan_disable);
1062 hci_req_add_le_scan_disable(req);
1063 }
1064
1065 break;
1066
1067 case DISCOVERY_RESOLVING:
1068 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1069 NAME_PENDING);
1070 if (!e)
1071 return;
1072
1073 bacpy(&cp.bdaddr, &e->data.bdaddr);
1074 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1075 &cp);
1076
1077 break;
1078
1079 default:
1080 /* Passive scanning */
1081 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1082 hci_req_add_le_scan_disable(req);
1083 break;
1084 }
1085}
1086
Johan Hedberg8b064a32014-02-24 14:52:22 +02001087static int clean_up_hci_state(struct hci_dev *hdev)
1088{
1089 struct hci_request req;
1090 struct hci_conn *conn;
1091
1092 hci_req_init(&req, hdev);
1093
1094 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1095 test_bit(HCI_PSCAN, &hdev->flags)) {
1096 u8 scan = 0x00;
1097 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1098 }
1099
1100 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1101 disable_advertising(&req);
1102
Johan Hedbergf8680f12014-06-10 14:05:59 +03001103 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001104
1105 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1106 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001107 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001108
Johan Hedbergc9910d02014-02-27 14:35:12 +02001109 switch (conn->state) {
1110 case BT_CONNECTED:
1111 case BT_CONFIG:
1112 dc.handle = cpu_to_le16(conn->handle);
1113 dc.reason = 0x15; /* Terminated due to Power Off */
1114 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1115 break;
1116 case BT_CONNECT:
1117 if (conn->type == LE_LINK)
1118 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1119 0, NULL);
1120 else if (conn->type == ACL_LINK)
1121 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1122 6, &conn->dst);
1123 break;
1124 case BT_CONNECT2:
1125 bacpy(&rej.bdaddr, &conn->dst);
1126 rej.reason = 0x15; /* Terminated due to Power Off */
1127 if (conn->type == ACL_LINK)
1128 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1129 sizeof(rej), &rej);
1130 else if (conn->type == SCO_LINK)
1131 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1132 sizeof(rej), &rej);
1133 break;
1134 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001135 }
1136
1137 return hci_req_run(&req, clean_up_hci_complete);
1138}
1139
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001140static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001141 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001142{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001143 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001144 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001145 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001147 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001148
Johan Hedberga7e80f22013-01-09 16:05:19 +02001149 if (cp->val != 0x00 && cp->val != 0x01)
1150 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1151 MGMT_STATUS_INVALID_PARAMS);
1152
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001153 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001154
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001155 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1156 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1157 MGMT_STATUS_BUSY);
1158 goto failed;
1159 }
1160
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001161 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1162 cancel_delayed_work(&hdev->power_off);
1163
1164 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001165 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1166 data, len);
1167 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001168 goto failed;
1169 }
1170 }
1171
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001172 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001173 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001174 goto failed;
1175 }
1176
Johan Hedberg03811012010-12-08 00:21:06 +02001177 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1178 if (!cmd) {
1179 err = -ENOMEM;
1180 goto failed;
1181 }
1182
Johan Hedberg8b064a32014-02-24 14:52:22 +02001183 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001184 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001185 err = 0;
1186 } else {
1187 /* Disconnect connections, stop scans, etc */
1188 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001189 if (!err)
1190 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1191 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001192
Johan Hedberg8b064a32014-02-24 14:52:22 +02001193 /* ENODATA means there were no HCI commands queued */
1194 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001195 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001196 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1197 err = 0;
1198 }
1199 }
Johan Hedberg03811012010-12-08 00:21:06 +02001200
1201failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001202 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 return err;
1204}
1205
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001206static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1207 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001208{
1209 struct sk_buff *skb;
1210 struct mgmt_hdr *hdr;
1211
Andre Guedes790eff42012-06-07 19:05:46 -03001212 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001213 if (!skb)
1214 return -ENOMEM;
1215
1216 hdr = (void *) skb_put(skb, sizeof(*hdr));
1217 hdr->opcode = cpu_to_le16(event);
1218 if (hdev)
1219 hdr->index = cpu_to_le16(hdev->id);
1220 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001221 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001222 hdr->len = cpu_to_le16(data_len);
1223
1224 if (data)
1225 memcpy(skb_put(skb, data_len), data, data_len);
1226
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001227 /* Time stamp */
1228 __net_timestamp(skb);
1229
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001230 hci_send_to_control(skb, skip_sk);
1231 kfree_skb(skb);
1232
1233 return 0;
1234}
1235
1236static int new_settings(struct hci_dev *hdev, struct sock *skip)
1237{
1238 __le32 ev;
1239
1240 ev = cpu_to_le32(get_current_settings(hdev));
1241
1242 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1243}
1244
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001245struct cmd_lookup {
1246 struct sock *sk;
1247 struct hci_dev *hdev;
1248 u8 mgmt_status;
1249};
1250
1251static void settings_rsp(struct pending_cmd *cmd, void *data)
1252{
1253 struct cmd_lookup *match = data;
1254
1255 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1256
1257 list_del(&cmd->list);
1258
1259 if (match->sk == NULL) {
1260 match->sk = cmd->sk;
1261 sock_hold(match->sk);
1262 }
1263
1264 mgmt_pending_free(cmd);
1265}
1266
1267static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1268{
1269 u8 *status = data;
1270
1271 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1272 mgmt_pending_remove(cmd);
1273}
1274
Johan Hedberge6fe7982013-10-02 15:45:22 +03001275static u8 mgmt_bredr_support(struct hci_dev *hdev)
1276{
1277 if (!lmp_bredr_capable(hdev))
1278 return MGMT_STATUS_NOT_SUPPORTED;
1279 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1280 return MGMT_STATUS_REJECTED;
1281 else
1282 return MGMT_STATUS_SUCCESS;
1283}
1284
1285static u8 mgmt_le_support(struct hci_dev *hdev)
1286{
1287 if (!lmp_le_capable(hdev))
1288 return MGMT_STATUS_NOT_SUPPORTED;
1289 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1290 return MGMT_STATUS_REJECTED;
1291 else
1292 return MGMT_STATUS_SUCCESS;
1293}
1294
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001295static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1296{
1297 struct pending_cmd *cmd;
1298 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001299 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001300 bool changed;
1301
1302 BT_DBG("status 0x%02x", status);
1303
1304 hci_dev_lock(hdev);
1305
1306 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1307 if (!cmd)
1308 goto unlock;
1309
1310 if (status) {
1311 u8 mgmt_err = mgmt_status(status);
1312 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001313 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001314 goto remove_cmd;
1315 }
1316
1317 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001318 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001319 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1320 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001321
1322 if (hdev->discov_timeout > 0) {
1323 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1324 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1325 to);
1326 }
1327 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001328 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1329 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001330 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001331
1332 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1333
1334 if (changed)
1335 new_settings(hdev, cmd->sk);
1336
Marcel Holtmann970ba522013-10-15 06:33:57 -07001337 /* When the discoverable mode gets changed, make sure
1338 * that class of device has the limited discoverable
1339 * bit correctly set.
1340 */
1341 hci_req_init(&req, hdev);
1342 update_class(&req);
1343 hci_req_run(&req, NULL);
1344
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001345remove_cmd:
1346 mgmt_pending_remove(cmd);
1347
1348unlock:
1349 hci_dev_unlock(hdev);
1350}
1351
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001352static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001353 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001354{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001355 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001356 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001357 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001358 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001359 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001360 int err;
1361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001362 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001363
Johan Hedberg9a43e252013-10-20 19:00:07 +03001364 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1365 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001366 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001367 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001368
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001369 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001370 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1371 MGMT_STATUS_INVALID_PARAMS);
1372
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001373 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001374
1375 /* Disabling discoverable requires that no timeout is set,
1376 * and enabling limited discoverable requires a timeout.
1377 */
1378 if ((cp->val == 0x00 && timeout > 0) ||
1379 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001380 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001381 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001382
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001383 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001384
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001385 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001386 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001387 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001388 goto failed;
1389 }
1390
1391 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001392 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001393 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001394 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001395 goto failed;
1396 }
1397
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001398 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001399 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001400 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001401 goto failed;
1402 }
1403
1404 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001405 bool changed = false;
1406
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001407 /* Setting limited discoverable when powered off is
1408 * not a valid operation since it requires a timeout
1409 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1410 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001411 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1412 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1413 changed = true;
1414 }
1415
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001416 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001417 if (err < 0)
1418 goto failed;
1419
1420 if (changed)
1421 err = new_settings(hdev, sk);
1422
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001423 goto failed;
1424 }
1425
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001426 /* If the current mode is the same, then just update the timeout
1427 * value with the new value. And if only the timeout gets updated,
1428 * then no need for any HCI transactions.
1429 */
1430 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1431 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1432 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001433 cancel_delayed_work(&hdev->discov_off);
1434 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001435
Marcel Holtmann36261542013-10-15 08:28:51 -07001436 if (cp->val && hdev->discov_timeout > 0) {
1437 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001438 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001439 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001440 }
1441
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001442 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001443 goto failed;
1444 }
1445
1446 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1447 if (!cmd) {
1448 err = -ENOMEM;
1449 goto failed;
1450 }
1451
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001452 /* Cancel any potential discoverable timeout that might be
1453 * still active and store new timeout value. The arming of
1454 * the timeout happens in the complete handler.
1455 */
1456 cancel_delayed_work(&hdev->discov_off);
1457 hdev->discov_timeout = timeout;
1458
Johan Hedbergb456f872013-10-19 23:38:22 +03001459 /* Limited discoverable mode */
1460 if (cp->val == 0x02)
1461 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1462 else
1463 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1464
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001465 hci_req_init(&req, hdev);
1466
Johan Hedberg9a43e252013-10-20 19:00:07 +03001467 /* The procedure for LE-only controllers is much simpler - just
1468 * update the advertising data.
1469 */
1470 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1471 goto update_ad;
1472
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001473 scan = SCAN_PAGE;
1474
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001475 if (cp->val) {
1476 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001477
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001478 if (cp->val == 0x02) {
1479 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001480 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001481 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1482 hci_cp.iac_lap[1] = 0x8b;
1483 hci_cp.iac_lap[2] = 0x9e;
1484 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1485 hci_cp.iac_lap[4] = 0x8b;
1486 hci_cp.iac_lap[5] = 0x9e;
1487 } else {
1488 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001489 hci_cp.num_iac = 1;
1490 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1491 hci_cp.iac_lap[1] = 0x8b;
1492 hci_cp.iac_lap[2] = 0x9e;
1493 }
1494
1495 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1496 (hci_cp.num_iac * 3) + 1, &hci_cp);
1497
1498 scan |= SCAN_INQUIRY;
1499 } else {
1500 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1501 }
1502
1503 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504
Johan Hedberg9a43e252013-10-20 19:00:07 +03001505update_ad:
1506 update_adv_data(&req);
1507
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001508 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001509 if (err < 0)
1510 mgmt_pending_remove(cmd);
1511
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001512failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001513 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001514 return err;
1515}
1516
Johan Hedberg406d7802013-03-15 17:07:09 -05001517static void write_fast_connectable(struct hci_request *req, bool enable)
1518{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001519 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001520 struct hci_cp_write_page_scan_activity acp;
1521 u8 type;
1522
Johan Hedberg547003b2013-10-21 16:51:53 +03001523 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1524 return;
1525
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001526 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1527 return;
1528
Johan Hedberg406d7802013-03-15 17:07:09 -05001529 if (enable) {
1530 type = PAGE_SCAN_TYPE_INTERLACED;
1531
1532 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001533 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001534 } else {
1535 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1536
1537 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001538 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001539 }
1540
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001541 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001542
Johan Hedbergbd98b992013-03-15 17:07:13 -05001543 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1544 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1545 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1546 sizeof(acp), &acp);
1547
1548 if (hdev->page_scan_type != type)
1549 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001550}
1551
Johan Hedberg2b76f452013-03-15 17:07:04 -05001552static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1553{
1554 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001555 struct mgmt_mode *cp;
1556 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001557
1558 BT_DBG("status 0x%02x", status);
1559
1560 hci_dev_lock(hdev);
1561
1562 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1563 if (!cmd)
1564 goto unlock;
1565
Johan Hedberg37438c12013-10-14 16:20:05 +03001566 if (status) {
1567 u8 mgmt_err = mgmt_status(status);
1568 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1569 goto remove_cmd;
1570 }
1571
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001572 cp = cmd->param;
1573 if (cp->val)
1574 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1575 else
1576 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1577
Johan Hedberg2b76f452013-03-15 17:07:04 -05001578 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1579
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001580 if (changed)
1581 new_settings(hdev, cmd->sk);
1582
Johan Hedberg37438c12013-10-14 16:20:05 +03001583remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001584 mgmt_pending_remove(cmd);
1585
1586unlock:
1587 hci_dev_unlock(hdev);
1588}
1589
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001590static int set_connectable_update_settings(struct hci_dev *hdev,
1591 struct sock *sk, u8 val)
1592{
1593 bool changed = false;
1594 int err;
1595
1596 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1597 changed = true;
1598
1599 if (val) {
1600 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1601 } else {
1602 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1603 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1604 }
1605
1606 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1607 if (err < 0)
1608 return err;
1609
1610 if (changed)
1611 return new_settings(hdev, sk);
1612
1613 return 0;
1614}
1615
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001616static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001617 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001618{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001619 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001620 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001621 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001622 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001623 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001624
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001625 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001626
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001627 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1628 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001629 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001630 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001631
Johan Hedberga7e80f22013-01-09 16:05:19 +02001632 if (cp->val != 0x00 && cp->val != 0x01)
1633 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1634 MGMT_STATUS_INVALID_PARAMS);
1635
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001636 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001637
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001638 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001639 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001640 goto failed;
1641 }
1642
1643 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001644 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001645 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001646 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001647 goto failed;
1648 }
1649
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001650 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1651 if (!cmd) {
1652 err = -ENOMEM;
1653 goto failed;
1654 }
1655
Johan Hedberg2b76f452013-03-15 17:07:04 -05001656 hci_req_init(&req, hdev);
1657
Johan Hedberg9a43e252013-10-20 19:00:07 +03001658 /* If BR/EDR is not enabled and we disable advertising as a
1659 * by-product of disabling connectable, we need to update the
1660 * advertising flags.
1661 */
1662 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1663 if (!cp->val) {
1664 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1665 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1666 }
1667 update_adv_data(&req);
1668 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001669 if (cp->val) {
1670 scan = SCAN_PAGE;
1671 } else {
1672 scan = 0;
1673
1674 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001675 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001676 cancel_delayed_work(&hdev->discov_off);
1677 }
1678
1679 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1680 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001681
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001682 /* If we're going from non-connectable to connectable or
1683 * vice-versa when fast connectable is enabled ensure that fast
1684 * connectable gets disabled. write_fast_connectable won't do
1685 * anything if the page scan parameters are already what they
1686 * should be.
1687 */
1688 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001689 write_fast_connectable(&req, false);
1690
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001691 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1692 hci_conn_num(hdev, LE_LINK) == 0) {
1693 disable_advertising(&req);
1694 enable_advertising(&req);
1695 }
1696
Johan Hedberg2b76f452013-03-15 17:07:04 -05001697 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001698 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001699 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001700 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001701 err = set_connectable_update_settings(hdev, sk,
1702 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001703 goto failed;
1704 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001705
1706failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001707 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001708 return err;
1709}
1710
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001711static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001712 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001713{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001714 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001715 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001716 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001717
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001718 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001719
Johan Hedberga7e80f22013-01-09 16:05:19 +02001720 if (cp->val != 0x00 && cp->val != 0x01)
1721 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1722 MGMT_STATUS_INVALID_PARAMS);
1723
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001724 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001725
1726 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001727 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001728 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001729 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001730
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001731 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001732 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001733 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001734
Marcel Holtmann55594352013-10-06 16:11:57 -07001735 if (changed)
1736 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001737
Marcel Holtmann55594352013-10-06 16:11:57 -07001738unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001739 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001740 return err;
1741}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001742
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001743static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1744 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001745{
1746 struct mgmt_mode *cp = data;
1747 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001748 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001749 int err;
1750
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001751 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001752
Johan Hedberge6fe7982013-10-02 15:45:22 +03001753 status = mgmt_bredr_support(hdev);
1754 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001755 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001756 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001757
Johan Hedberga7e80f22013-01-09 16:05:19 +02001758 if (cp->val != 0x00 && cp->val != 0x01)
1759 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1760 MGMT_STATUS_INVALID_PARAMS);
1761
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001762 hci_dev_lock(hdev);
1763
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001764 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001765 bool changed = false;
1766
1767 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001768 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001769 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1770 changed = true;
1771 }
1772
1773 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1774 if (err < 0)
1775 goto failed;
1776
1777 if (changed)
1778 err = new_settings(hdev, sk);
1779
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001780 goto failed;
1781 }
1782
1783 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001784 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001785 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001786 goto failed;
1787 }
1788
1789 val = !!cp->val;
1790
1791 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1792 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1793 goto failed;
1794 }
1795
1796 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1797 if (!cmd) {
1798 err = -ENOMEM;
1799 goto failed;
1800 }
1801
1802 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1803 if (err < 0) {
1804 mgmt_pending_remove(cmd);
1805 goto failed;
1806 }
1807
1808failed:
1809 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001810 return err;
1811}
1812
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001813static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001814{
1815 struct mgmt_mode *cp = data;
1816 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001817 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001818 int err;
1819
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001820 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001821
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001822 status = mgmt_bredr_support(hdev);
1823 if (status)
1824 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1825
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001826 if (!lmp_ssp_capable(hdev))
1827 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1828 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001829
Johan Hedberga7e80f22013-01-09 16:05:19 +02001830 if (cp->val != 0x00 && cp->val != 0x01)
1831 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1832 MGMT_STATUS_INVALID_PARAMS);
1833
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001834 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001835
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001836 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001837 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001838
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001839 if (cp->val) {
1840 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1841 &hdev->dev_flags);
1842 } else {
1843 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1844 &hdev->dev_flags);
1845 if (!changed)
1846 changed = test_and_clear_bit(HCI_HS_ENABLED,
1847 &hdev->dev_flags);
1848 else
1849 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001850 }
1851
1852 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1853 if (err < 0)
1854 goto failed;
1855
1856 if (changed)
1857 err = new_settings(hdev, sk);
1858
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001859 goto failed;
1860 }
1861
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001862 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1863 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001864 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1865 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001866 goto failed;
1867 }
1868
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001869 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001870 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1871 goto failed;
1872 }
1873
1874 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1875 if (!cmd) {
1876 err = -ENOMEM;
1877 goto failed;
1878 }
1879
Johan Hedberg37699722014-06-24 14:00:27 +03001880 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1881 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1882 sizeof(cp->val), &cp->val);
1883
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001884 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001885 if (err < 0) {
1886 mgmt_pending_remove(cmd);
1887 goto failed;
1888 }
1889
1890failed:
1891 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001892 return err;
1893}
1894
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001895static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001896{
1897 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001898 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001899 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001900 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001901
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001902 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001903
Johan Hedberge6fe7982013-10-02 15:45:22 +03001904 status = mgmt_bredr_support(hdev);
1905 if (status)
1906 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001907
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001908 if (!lmp_ssp_capable(hdev))
1909 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1910 MGMT_STATUS_NOT_SUPPORTED);
1911
1912 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1913 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1914 MGMT_STATUS_REJECTED);
1915
Johan Hedberga7e80f22013-01-09 16:05:19 +02001916 if (cp->val != 0x00 && cp->val != 0x01)
1917 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1918 MGMT_STATUS_INVALID_PARAMS);
1919
Marcel Holtmannee392692013-10-01 22:59:23 -07001920 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001921
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001922 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001923 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001924 } else {
1925 if (hdev_is_powered(hdev)) {
1926 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1927 MGMT_STATUS_REJECTED);
1928 goto unlock;
1929 }
1930
Marcel Holtmannee392692013-10-01 22:59:23 -07001931 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001932 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001933
1934 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1935 if (err < 0)
1936 goto unlock;
1937
1938 if (changed)
1939 err = new_settings(hdev, sk);
1940
1941unlock:
1942 hci_dev_unlock(hdev);
1943 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001944}
1945
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001946static void le_enable_complete(struct hci_dev *hdev, u8 status)
1947{
1948 struct cmd_lookup match = { NULL, hdev };
1949
1950 if (status) {
1951 u8 mgmt_err = mgmt_status(status);
1952
1953 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1954 &mgmt_err);
1955 return;
1956 }
1957
1958 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1959
1960 new_settings(hdev, match.sk);
1961
1962 if (match.sk)
1963 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001964
1965 /* Make sure the controller has a good default for
1966 * advertising data. Restrict the update to when LE
1967 * has actually been enabled. During power on, the
1968 * update in powered_update_hci will take care of it.
1969 */
1970 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1971 struct hci_request req;
1972
1973 hci_dev_lock(hdev);
1974
1975 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001976 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001977 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001978 hci_req_run(&req, NULL);
1979
1980 hci_dev_unlock(hdev);
1981 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001982}
1983
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001984static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001985{
1986 struct mgmt_mode *cp = data;
1987 struct hci_cp_write_le_host_supported hci_cp;
1988 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001989 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001990 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001991 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001992
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001993 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001994
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001995 if (!lmp_le_capable(hdev))
1996 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1997 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001998
Johan Hedberga7e80f22013-01-09 16:05:19 +02001999 if (cp->val != 0x00 && cp->val != 0x01)
2000 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2001 MGMT_STATUS_INVALID_PARAMS);
2002
Johan Hedbergc73eee92013-04-19 18:35:21 +03002003 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002004 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002005 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2006 MGMT_STATUS_REJECTED);
2007
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002008 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002009
2010 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002011 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002012
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002013 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002014 bool changed = false;
2015
2016 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2017 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2018 changed = true;
2019 }
2020
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002021 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2022 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002023 changed = true;
2024 }
2025
Johan Hedberg06199cf2012-02-22 16:37:11 +02002026 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2027 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002028 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002029
2030 if (changed)
2031 err = new_settings(hdev, sk);
2032
Johan Hedberg1de028c2012-02-29 19:55:35 -08002033 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002034 }
2035
Johan Hedberg4375f102013-09-25 13:26:10 +03002036 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2037 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002038 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002039 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002040 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002041 }
2042
2043 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2044 if (!cmd) {
2045 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002046 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002047 }
2048
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002049 hci_req_init(&req, hdev);
2050
Johan Hedberg06199cf2012-02-22 16:37:11 +02002051 memset(&hci_cp, 0, sizeof(hci_cp));
2052
2053 if (val) {
2054 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002055 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002056 } else {
2057 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2058 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002059 }
2060
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002061 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2062 &hci_cp);
2063
2064 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302065 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002066 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002067
Johan Hedberg1de028c2012-02-29 19:55:35 -08002068unlock:
2069 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002070 return err;
2071}
2072
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002073/* This is a helper function to test for pending mgmt commands that can
2074 * cause CoD or EIR HCI commands. We can only allow one such pending
2075 * mgmt command at a time since otherwise we cannot easily track what
2076 * the current values are, will be, and based on that calculate if a new
2077 * HCI command needs to be sent and if yes with what value.
2078 */
2079static bool pending_eir_or_class(struct hci_dev *hdev)
2080{
2081 struct pending_cmd *cmd;
2082
2083 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2084 switch (cmd->opcode) {
2085 case MGMT_OP_ADD_UUID:
2086 case MGMT_OP_REMOVE_UUID:
2087 case MGMT_OP_SET_DEV_CLASS:
2088 case MGMT_OP_SET_POWERED:
2089 return true;
2090 }
2091 }
2092
2093 return false;
2094}
2095
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002096static const u8 bluetooth_base_uuid[] = {
2097 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2098 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2099};
2100
2101static u8 get_uuid_size(const u8 *uuid)
2102{
2103 u32 val;
2104
2105 if (memcmp(uuid, bluetooth_base_uuid, 12))
2106 return 128;
2107
2108 val = get_unaligned_le32(&uuid[12]);
2109 if (val > 0xffff)
2110 return 32;
2111
2112 return 16;
2113}
2114
Johan Hedberg92da6092013-03-15 17:06:55 -05002115static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2116{
2117 struct pending_cmd *cmd;
2118
2119 hci_dev_lock(hdev);
2120
2121 cmd = mgmt_pending_find(mgmt_op, hdev);
2122 if (!cmd)
2123 goto unlock;
2124
2125 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2126 hdev->dev_class, 3);
2127
2128 mgmt_pending_remove(cmd);
2129
2130unlock:
2131 hci_dev_unlock(hdev);
2132}
2133
2134static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2135{
2136 BT_DBG("status 0x%02x", status);
2137
2138 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2139}
2140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002141static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002142{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002143 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002144 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002145 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002146 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002147 int err;
2148
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002149 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002150
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002151 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002152
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002153 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002155 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002156 goto failed;
2157 }
2158
Andre Guedes92c4c202012-06-07 19:05:44 -03002159 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002160 if (!uuid) {
2161 err = -ENOMEM;
2162 goto failed;
2163 }
2164
2165 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002166 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002167 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002168
Johan Hedbergde66aa62013-01-27 00:31:27 +02002169 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002170
Johan Hedberg890ea892013-03-15 17:06:52 -05002171 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002172
Johan Hedberg890ea892013-03-15 17:06:52 -05002173 update_class(&req);
2174 update_eir(&req);
2175
Johan Hedberg92da6092013-03-15 17:06:55 -05002176 err = hci_req_run(&req, add_uuid_complete);
2177 if (err < 0) {
2178 if (err != -ENODATA)
2179 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002181 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002182 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002183 goto failed;
2184 }
2185
2186 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002187 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002188 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002189 goto failed;
2190 }
2191
2192 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002193
2194failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002195 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002196 return err;
2197}
2198
Johan Hedberg24b78d02012-02-23 23:24:30 +02002199static bool enable_service_cache(struct hci_dev *hdev)
2200{
2201 if (!hdev_is_powered(hdev))
2202 return false;
2203
2204 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002205 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2206 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002207 return true;
2208 }
2209
2210 return false;
2211}
2212
Johan Hedberg92da6092013-03-15 17:06:55 -05002213static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2214{
2215 BT_DBG("status 0x%02x", status);
2216
2217 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2218}
2219
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002220static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002221 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002222{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002223 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002224 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002225 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002226 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 -05002227 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002228 int err, found;
2229
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002230 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002231
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002232 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002233
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002234 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002235 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002236 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002237 goto unlock;
2238 }
2239
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002240 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002241 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002242
Johan Hedberg24b78d02012-02-23 23:24:30 +02002243 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002244 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002245 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002246 goto unlock;
2247 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002248
Johan Hedberg9246a862012-02-23 21:33:16 +02002249 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002250 }
2251
2252 found = 0;
2253
Johan Hedberg056341c2013-01-27 00:31:30 +02002254 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002255 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2256 continue;
2257
2258 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002259 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002260 found++;
2261 }
2262
2263 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002264 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002265 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002266 goto unlock;
2267 }
2268
Johan Hedberg9246a862012-02-23 21:33:16 +02002269update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002270 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002271
Johan Hedberg890ea892013-03-15 17:06:52 -05002272 update_class(&req);
2273 update_eir(&req);
2274
Johan Hedberg92da6092013-03-15 17:06:55 -05002275 err = hci_req_run(&req, remove_uuid_complete);
2276 if (err < 0) {
2277 if (err != -ENODATA)
2278 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002279
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002280 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002281 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002282 goto unlock;
2283 }
2284
2285 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002286 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002287 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002288 goto unlock;
2289 }
2290
2291 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002292
2293unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002294 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002295 return err;
2296}
2297
Johan Hedberg92da6092013-03-15 17:06:55 -05002298static void set_class_complete(struct hci_dev *hdev, u8 status)
2299{
2300 BT_DBG("status 0x%02x", status);
2301
2302 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2303}
2304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002305static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002306 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002307{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002308 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002309 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002310 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002311 int err;
2312
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002313 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002314
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002315 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002316 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2317 MGMT_STATUS_NOT_SUPPORTED);
2318
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002319 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002320
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002321 if (pending_eir_or_class(hdev)) {
2322 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2323 MGMT_STATUS_BUSY);
2324 goto unlock;
2325 }
2326
2327 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2328 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2329 MGMT_STATUS_INVALID_PARAMS);
2330 goto unlock;
2331 }
2332
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002333 hdev->major_class = cp->major;
2334 hdev->minor_class = cp->minor;
2335
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002336 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002337 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002338 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002339 goto unlock;
2340 }
2341
Johan Hedberg890ea892013-03-15 17:06:52 -05002342 hci_req_init(&req, hdev);
2343
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002344 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002345 hci_dev_unlock(hdev);
2346 cancel_delayed_work_sync(&hdev->service_cache);
2347 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002348 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002349 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002350
Johan Hedberg890ea892013-03-15 17:06:52 -05002351 update_class(&req);
2352
Johan Hedberg92da6092013-03-15 17:06:55 -05002353 err = hci_req_run(&req, set_class_complete);
2354 if (err < 0) {
2355 if (err != -ENODATA)
2356 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002357
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002358 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002359 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002360 goto unlock;
2361 }
2362
2363 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002364 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002365 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002366 goto unlock;
2367 }
2368
2369 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002370
Johan Hedbergb5235a62012-02-21 14:32:24 +02002371unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002372 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002373 return err;
2374}
2375
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002376static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002377 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002378{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002379 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002380 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002381 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002382 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002383
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002384 BT_DBG("request for %s", hdev->name);
2385
2386 if (!lmp_bredr_capable(hdev))
2387 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2388 MGMT_STATUS_NOT_SUPPORTED);
2389
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002390 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002391
Johan Hedberg86742e12011-11-07 23:13:38 +02002392 expected_len = sizeof(*cp) + key_count *
2393 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002394 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002395 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002396 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002397 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002398 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002399 }
2400
Johan Hedberg4ae14302013-01-20 14:27:13 +02002401 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2402 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2403 MGMT_STATUS_INVALID_PARAMS);
2404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002405 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002406 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002407
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002408 for (i = 0; i < key_count; i++) {
2409 struct mgmt_link_key_info *key = &cp->keys[i];
2410
Marcel Holtmann8e991132014-01-10 02:07:25 -08002411 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002412 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2413 MGMT_STATUS_INVALID_PARAMS);
2414 }
2415
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002416 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002417
2418 hci_link_keys_clear(hdev);
2419
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002420 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002421 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2422 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002423 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002424 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2425 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002426
2427 if (changed)
2428 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002429
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002430 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002431 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002432
Johan Hedberg58e92932014-06-24 14:00:26 +03002433 /* Always ignore debug keys and require a new pairing if
2434 * the user wants to use them.
2435 */
2436 if (key->type == HCI_LK_DEBUG_COMBINATION)
2437 continue;
2438
Johan Hedberg7652ff62014-06-24 13:15:49 +03002439 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2440 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002441 }
2442
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002443 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002444
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002445 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002446
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002447 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002448}
2449
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002450static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002451 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002452{
2453 struct mgmt_ev_device_unpaired ev;
2454
2455 bacpy(&ev.addr.bdaddr, bdaddr);
2456 ev.addr.type = addr_type;
2457
2458 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002459 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002460}
2461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002462static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002463 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002464{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002465 struct mgmt_cp_unpair_device *cp = data;
2466 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002467 struct hci_cp_disconnect dc;
2468 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002469 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002470 int err;
2471
Johan Hedberga8a1d192011-11-10 15:54:38 +02002472 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002473 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2474 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002475
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002476 if (!bdaddr_type_is_valid(cp->addr.type))
2477 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2478 MGMT_STATUS_INVALID_PARAMS,
2479 &rp, sizeof(rp));
2480
Johan Hedberg118da702013-01-20 14:27:20 +02002481 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2482 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2483 MGMT_STATUS_INVALID_PARAMS,
2484 &rp, sizeof(rp));
2485
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002486 hci_dev_lock(hdev);
2487
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002488 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002491 goto unlock;
2492 }
2493
Johan Hedberge0b2b272014-02-18 17:14:31 +02002494 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002495 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002496 } else {
2497 u8 addr_type;
2498
2499 if (cp->addr.type == BDADDR_LE_PUBLIC)
2500 addr_type = ADDR_LE_DEV_PUBLIC;
2501 else
2502 addr_type = ADDR_LE_DEV_RANDOM;
2503
Johan Hedberga7ec7332014-02-18 17:14:35 +02002504 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2505
Andre Guedesa9b0a042014-02-26 20:21:52 -03002506 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2507
Johan Hedberge0b2b272014-02-18 17:14:31 +02002508 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2509 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002510
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002511 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002512 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002513 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002514 goto unlock;
2515 }
2516
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002517 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002518 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002519 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002520 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002521 else
2522 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002523 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002524 } else {
2525 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002526 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002527
Johan Hedberga8a1d192011-11-10 15:54:38 +02002528 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002529 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002530 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002531 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002532 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002533 }
2534
Johan Hedberg124f6e32012-02-09 13:50:12 +02002535 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002536 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002537 if (!cmd) {
2538 err = -ENOMEM;
2539 goto unlock;
2540 }
2541
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002542 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002543 dc.reason = 0x13; /* Remote User Terminated Connection */
2544 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2545 if (err < 0)
2546 mgmt_pending_remove(cmd);
2547
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002548unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002549 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002550 return err;
2551}
2552
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002553static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002554 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002555{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002556 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002557 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002558 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002559 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002560 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002561 int err;
2562
2563 BT_DBG("");
2564
Johan Hedberg06a63b12013-01-20 14:27:21 +02002565 memset(&rp, 0, sizeof(rp));
2566 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2567 rp.addr.type = cp->addr.type;
2568
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002569 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002570 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2571 MGMT_STATUS_INVALID_PARAMS,
2572 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002573
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002574 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002575
2576 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002577 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2578 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002579 goto failed;
2580 }
2581
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002582 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002583 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2584 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002585 goto failed;
2586 }
2587
Andre Guedes591f47f2012-04-24 21:02:49 -03002588 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002589 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2590 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002591 else
2592 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002593
Vishal Agarwalf9607272012-06-13 05:32:43 +05302594 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002595 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2596 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002597 goto failed;
2598 }
2599
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002600 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002601 if (!cmd) {
2602 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002603 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002604 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002605
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002606 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002607 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002608
2609 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2610 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002611 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002612
2613failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002614 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002615 return err;
2616}
2617
Andre Guedes57c14772012-04-24 21:02:50 -03002618static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002619{
2620 switch (link_type) {
2621 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002622 switch (addr_type) {
2623 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002624 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002625
Johan Hedberg48264f02011-11-09 13:58:58 +02002626 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002627 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002628 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002629 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002630
Johan Hedberg4c659c32011-11-07 23:13:39 +02002631 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002632 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002633 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002634 }
2635}
2636
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002637static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2638 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002639{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002640 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002641 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002642 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002643 int err;
2644 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002645
2646 BT_DBG("");
2647
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002648 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002649
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002650 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002651 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002652 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002653 goto unlock;
2654 }
2655
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002656 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002657 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2658 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002659 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002660 }
2661
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002662 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002663 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002664 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002665 err = -ENOMEM;
2666 goto unlock;
2667 }
2668
Johan Hedberg2784eb42011-01-21 13:56:35 +02002669 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002670 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002671 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2672 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002673 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002674 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002675 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002676 continue;
2677 i++;
2678 }
2679
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002680 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002681
Johan Hedberg4c659c32011-11-07 23:13:39 +02002682 /* Recalculate length in case of filtered SCO connections, etc */
2683 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002684
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002685 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002686 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002687
Johan Hedberga38528f2011-01-22 06:46:43 +02002688 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002689
2690unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002691 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002692 return err;
2693}
2694
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002695static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002696 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002697{
2698 struct pending_cmd *cmd;
2699 int err;
2700
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002701 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002702 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002703 if (!cmd)
2704 return -ENOMEM;
2705
Johan Hedbergd8457692012-02-17 14:24:57 +02002706 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002707 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002708 if (err < 0)
2709 mgmt_pending_remove(cmd);
2710
2711 return err;
2712}
2713
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002714static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002715 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002716{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002717 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002718 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002719 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002720 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002721 int err;
2722
2723 BT_DBG("");
2724
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002725 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002726
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002727 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002728 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002729 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002730 goto failed;
2731 }
2732
Johan Hedbergd8457692012-02-17 14:24:57 +02002733 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002734 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002735 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002736 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002737 goto failed;
2738 }
2739
2740 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002741 struct mgmt_cp_pin_code_neg_reply ncp;
2742
2743 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002744
2745 BT_ERR("PIN code is not 16 bytes long");
2746
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002747 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002748 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002749 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002750 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002751
2752 goto failed;
2753 }
2754
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002755 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002756 if (!cmd) {
2757 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002758 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002759 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002760
Johan Hedbergd8457692012-02-17 14:24:57 +02002761 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002762 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002763 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002764
2765 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2766 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002767 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002768
2769failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002770 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002771 return err;
2772}
2773
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002774static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2775 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002776{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002777 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002778
2779 BT_DBG("");
2780
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002781 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2782 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2783 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2784
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002785 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002786
2787 hdev->io_capability = cp->io_capability;
2788
2789 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002790 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002791
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002792 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002793
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002794 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2795 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002796}
2797
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002798static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002799{
2800 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002801 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002802
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002803 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002804 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2805 continue;
2806
Johan Hedberge9a416b2011-02-19 12:05:56 -03002807 if (cmd->user_data != conn)
2808 continue;
2809
2810 return cmd;
2811 }
2812
2813 return NULL;
2814}
2815
2816static void pairing_complete(struct pending_cmd *cmd, u8 status)
2817{
2818 struct mgmt_rp_pair_device rp;
2819 struct hci_conn *conn = cmd->user_data;
2820
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002821 bacpy(&rp.addr.bdaddr, &conn->dst);
2822 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002823
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002824 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002825 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002826
2827 /* So we don't get further callbacks for this connection */
2828 conn->connect_cfm_cb = NULL;
2829 conn->security_cfm_cb = NULL;
2830 conn->disconn_cfm_cb = NULL;
2831
David Herrmann76a68ba2013-04-06 20:28:37 +02002832 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002833
Johan Hedberga664b5b2011-02-19 12:06:02 -03002834 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002835}
2836
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002837void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2838{
2839 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2840 struct pending_cmd *cmd;
2841
2842 cmd = find_pairing(conn);
2843 if (cmd)
2844 pairing_complete(cmd, status);
2845}
2846
Johan Hedberge9a416b2011-02-19 12:05:56 -03002847static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2848{
2849 struct pending_cmd *cmd;
2850
2851 BT_DBG("status %u", status);
2852
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002853 cmd = find_pairing(conn);
2854 if (!cmd)
2855 BT_DBG("Unable to find a pending command");
2856 else
Johan Hedberge2113262012-02-18 15:20:03 +02002857 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002858}
2859
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002860static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302861{
2862 struct pending_cmd *cmd;
2863
2864 BT_DBG("status %u", status);
2865
2866 if (!status)
2867 return;
2868
2869 cmd = find_pairing(conn);
2870 if (!cmd)
2871 BT_DBG("Unable to find a pending command");
2872 else
2873 pairing_complete(cmd, mgmt_status(status));
2874}
2875
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002876static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002877 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002878{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002879 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002880 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002881 struct pending_cmd *cmd;
2882 u8 sec_level, auth_type;
2883 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002884 int err;
2885
2886 BT_DBG("");
2887
Szymon Jancf950a30e2013-01-18 12:48:07 +01002888 memset(&rp, 0, sizeof(rp));
2889 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2890 rp.addr.type = cp->addr.type;
2891
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002892 if (!bdaddr_type_is_valid(cp->addr.type))
2893 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2894 MGMT_STATUS_INVALID_PARAMS,
2895 &rp, sizeof(rp));
2896
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002897 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2898 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2899 MGMT_STATUS_INVALID_PARAMS,
2900 &rp, sizeof(rp));
2901
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002902 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002903
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002904 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002905 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2906 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002907 goto unlock;
2908 }
2909
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002910 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002911 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002912
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002913 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002914 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2915 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002916 } else {
2917 u8 addr_type;
2918
2919 /* Convert from L2CAP channel address type to HCI address type
2920 */
2921 if (cp->addr.type == BDADDR_LE_PUBLIC)
2922 addr_type = ADDR_LE_DEV_PUBLIC;
2923 else
2924 addr_type = ADDR_LE_DEV_RANDOM;
2925
2926 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002927 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002928 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002929
Ville Tervo30e76272011-02-22 16:10:53 -03002930 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002931 int status;
2932
2933 if (PTR_ERR(conn) == -EBUSY)
2934 status = MGMT_STATUS_BUSY;
2935 else
2936 status = MGMT_STATUS_CONNECT_FAILED;
2937
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002938 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002939 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002940 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002941 goto unlock;
2942 }
2943
2944 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002945 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002946 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002947 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002948 goto unlock;
2949 }
2950
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002951 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002952 if (!cmd) {
2953 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002954 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002955 goto unlock;
2956 }
2957
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002958 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002959 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002960 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002961 conn->security_cfm_cb = pairing_complete_cb;
2962 conn->disconn_cfm_cb = pairing_complete_cb;
2963 } else {
2964 conn->connect_cfm_cb = le_pairing_complete_cb;
2965 conn->security_cfm_cb = le_pairing_complete_cb;
2966 conn->disconn_cfm_cb = le_pairing_complete_cb;
2967 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002968
Johan Hedberge9a416b2011-02-19 12:05:56 -03002969 conn->io_capability = cp->io_cap;
2970 cmd->user_data = conn;
2971
2972 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002973 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002974 pairing_complete(cmd, 0);
2975
2976 err = 0;
2977
2978unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002979 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002980 return err;
2981}
2982
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002983static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2984 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002985{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002986 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002987 struct pending_cmd *cmd;
2988 struct hci_conn *conn;
2989 int err;
2990
2991 BT_DBG("");
2992
Johan Hedberg28424702012-02-02 04:02:29 +02002993 hci_dev_lock(hdev);
2994
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002995 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002996 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002997 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002998 goto unlock;
2999 }
3000
Johan Hedberg28424702012-02-02 04:02:29 +02003001 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3002 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003003 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003004 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003005 goto unlock;
3006 }
3007
3008 conn = cmd->user_data;
3009
3010 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003011 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003012 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003013 goto unlock;
3014 }
3015
3016 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3017
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003018 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003019 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003020unlock:
3021 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003022 return err;
3023}
3024
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003025static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003026 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003027 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003028{
Johan Hedberga5c29682011-02-19 12:05:57 -03003029 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003030 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003031 int err;
3032
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003033 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003034
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003035 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003036 err = cmd_complete(sk, hdev->id, mgmt_op,
3037 MGMT_STATUS_NOT_POWERED, addr,
3038 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003039 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003040 }
3041
Johan Hedberg1707c602013-03-15 17:07:15 -05003042 if (addr->type == BDADDR_BREDR)
3043 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003044 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003045 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003046
Johan Hedberg272d90d2012-02-09 15:26:12 +02003047 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003048 err = cmd_complete(sk, hdev->id, mgmt_op,
3049 MGMT_STATUS_NOT_CONNECTED, addr,
3050 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003051 goto done;
3052 }
3053
Johan Hedberg1707c602013-03-15 17:07:15 -05003054 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Johan Hedbergc73f94b2014-06-13 10:22:28 +03003055 /* Continue with pairing via SMP. The hdev lock must be
3056 * released as SMP may try to recquire it for crypto
3057 * purposes.
3058 */
3059 hci_dev_unlock(hdev);
Brian Gix5fe57d92011-12-21 16:12:13 -08003060 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Johan Hedbergc73f94b2014-06-13 10:22:28 +03003061 hci_dev_lock(hdev);
Brian Gix47c15e22011-11-16 13:53:14 -08003062
Brian Gix5fe57d92011-12-21 16:12:13 -08003063 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003064 err = cmd_complete(sk, hdev->id, mgmt_op,
3065 MGMT_STATUS_SUCCESS, addr,
3066 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003067 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003068 err = cmd_complete(sk, hdev->id, mgmt_op,
3069 MGMT_STATUS_FAILED, addr,
3070 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003071
Brian Gix47c15e22011-11-16 13:53:14 -08003072 goto done;
3073 }
3074
Johan Hedberg1707c602013-03-15 17:07:15 -05003075 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003076 if (!cmd) {
3077 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003078 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003079 }
3080
Brian Gix0df4c182011-11-16 13:53:13 -08003081 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003082 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3083 struct hci_cp_user_passkey_reply cp;
3084
Johan Hedberg1707c602013-03-15 17:07:15 -05003085 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003086 cp.passkey = passkey;
3087 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3088 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003089 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3090 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003091
Johan Hedberga664b5b2011-02-19 12:06:02 -03003092 if (err < 0)
3093 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003094
Brian Gix0df4c182011-11-16 13:53:13 -08003095done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003096 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003097 return err;
3098}
3099
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303100static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3101 void *data, u16 len)
3102{
3103 struct mgmt_cp_pin_code_neg_reply *cp = data;
3104
3105 BT_DBG("");
3106
Johan Hedberg1707c602013-03-15 17:07:15 -05003107 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303108 MGMT_OP_PIN_CODE_NEG_REPLY,
3109 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3110}
3111
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003112static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3113 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003114{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003115 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003116
3117 BT_DBG("");
3118
3119 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003120 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003121 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003122
Johan Hedberg1707c602013-03-15 17:07:15 -05003123 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003124 MGMT_OP_USER_CONFIRM_REPLY,
3125 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003126}
3127
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003128static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003129 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003130{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003131 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003132
3133 BT_DBG("");
3134
Johan Hedberg1707c602013-03-15 17:07:15 -05003135 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003136 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3137 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003138}
3139
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003140static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3141 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003142{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003143 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003144
3145 BT_DBG("");
3146
Johan Hedberg1707c602013-03-15 17:07:15 -05003147 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003148 MGMT_OP_USER_PASSKEY_REPLY,
3149 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003150}
3151
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003152static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003153 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003154{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003155 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003156
3157 BT_DBG("");
3158
Johan Hedberg1707c602013-03-15 17:07:15 -05003159 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003160 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3161 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003162}
3163
Johan Hedberg13928972013-03-15 17:07:00 -05003164static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003165{
Johan Hedberg13928972013-03-15 17:07:00 -05003166 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003167 struct hci_cp_write_local_name cp;
3168
Johan Hedberg13928972013-03-15 17:07:00 -05003169 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003170
Johan Hedberg890ea892013-03-15 17:06:52 -05003171 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003172}
3173
Johan Hedberg13928972013-03-15 17:07:00 -05003174static void set_name_complete(struct hci_dev *hdev, u8 status)
3175{
3176 struct mgmt_cp_set_local_name *cp;
3177 struct pending_cmd *cmd;
3178
3179 BT_DBG("status 0x%02x", status);
3180
3181 hci_dev_lock(hdev);
3182
3183 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3184 if (!cmd)
3185 goto unlock;
3186
3187 cp = cmd->param;
3188
3189 if (status)
3190 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3191 mgmt_status(status));
3192 else
3193 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3194 cp, sizeof(*cp));
3195
3196 mgmt_pending_remove(cmd);
3197
3198unlock:
3199 hci_dev_unlock(hdev);
3200}
3201
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003202static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003203 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003204{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003205 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003206 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003207 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003208 int err;
3209
3210 BT_DBG("");
3211
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003212 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003213
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003214 /* If the old values are the same as the new ones just return a
3215 * direct command complete event.
3216 */
3217 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3218 !memcmp(hdev->short_name, cp->short_name,
3219 sizeof(hdev->short_name))) {
3220 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3221 data, len);
3222 goto failed;
3223 }
3224
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003225 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003226
Johan Hedbergb5235a62012-02-21 14:32:24 +02003227 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003228 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003229
3230 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003231 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003232 if (err < 0)
3233 goto failed;
3234
3235 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003236 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003237
Johan Hedbergb5235a62012-02-21 14:32:24 +02003238 goto failed;
3239 }
3240
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003241 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003242 if (!cmd) {
3243 err = -ENOMEM;
3244 goto failed;
3245 }
3246
Johan Hedberg13928972013-03-15 17:07:00 -05003247 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3248
Johan Hedberg890ea892013-03-15 17:06:52 -05003249 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003250
3251 if (lmp_bredr_capable(hdev)) {
3252 update_name(&req);
3253 update_eir(&req);
3254 }
3255
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003256 /* The name is stored in the scan response data and so
3257 * no need to udpate the advertising data here.
3258 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003259 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003260 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003261
Johan Hedberg13928972013-03-15 17:07:00 -05003262 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003263 if (err < 0)
3264 mgmt_pending_remove(cmd);
3265
3266failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003267 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003268 return err;
3269}
3270
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003271static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003272 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003273{
Szymon Jancc35938b2011-03-22 13:12:21 +01003274 struct pending_cmd *cmd;
3275 int err;
3276
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003277 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003278
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003279 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003280
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003281 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003282 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003283 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003284 goto unlock;
3285 }
3286
Andre Guedes9a1a1992012-07-24 15:03:48 -03003287 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003288 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003289 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003290 goto unlock;
3291 }
3292
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003293 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003294 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003295 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003296 goto unlock;
3297 }
3298
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003299 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003300 if (!cmd) {
3301 err = -ENOMEM;
3302 goto unlock;
3303 }
3304
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003305 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3306 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3307 0, NULL);
3308 else
3309 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3310
Szymon Jancc35938b2011-03-22 13:12:21 +01003311 if (err < 0)
3312 mgmt_pending_remove(cmd);
3313
3314unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003315 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003316 return err;
3317}
3318
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003319static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003320 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003321{
Szymon Janc2763eda2011-03-22 13:12:22 +01003322 int err;
3323
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003324 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003325
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003326 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003327
Marcel Holtmannec109112014-01-10 02:07:30 -08003328 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3329 struct mgmt_cp_add_remote_oob_data *cp = data;
3330 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003331
Marcel Holtmannec109112014-01-10 02:07:30 -08003332 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3333 cp->hash, cp->randomizer);
3334 if (err < 0)
3335 status = MGMT_STATUS_FAILED;
3336 else
3337 status = MGMT_STATUS_SUCCESS;
3338
3339 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3340 status, &cp->addr, sizeof(cp->addr));
3341 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3342 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3343 u8 status;
3344
3345 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3346 cp->hash192,
3347 cp->randomizer192,
3348 cp->hash256,
3349 cp->randomizer256);
3350 if (err < 0)
3351 status = MGMT_STATUS_FAILED;
3352 else
3353 status = MGMT_STATUS_SUCCESS;
3354
3355 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3356 status, &cp->addr, sizeof(cp->addr));
3357 } else {
3358 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3359 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3360 MGMT_STATUS_INVALID_PARAMS);
3361 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003362
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003363 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003364 return err;
3365}
3366
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003367static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003368 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003369{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003370 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003371 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003372 int err;
3373
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003374 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003375
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003376 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003377
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003378 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003379 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003380 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003381 else
Szymon Janca6785be2012-12-13 15:11:21 +01003382 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003383
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003384 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003385 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003386
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003387 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003388 return err;
3389}
3390
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003391static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3392{
3393 struct pending_cmd *cmd;
3394 u8 type;
3395 int err;
3396
3397 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3398
3399 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3400 if (!cmd)
3401 return -ENOENT;
3402
3403 type = hdev->discovery.type;
3404
3405 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3406 &type, sizeof(type));
3407 mgmt_pending_remove(cmd);
3408
3409 return err;
3410}
3411
Andre Guedes7c307722013-04-30 15:29:28 -03003412static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3413{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003414 unsigned long timeout = 0;
3415
Andre Guedes7c307722013-04-30 15:29:28 -03003416 BT_DBG("status %d", status);
3417
3418 if (status) {
3419 hci_dev_lock(hdev);
3420 mgmt_start_discovery_failed(hdev, status);
3421 hci_dev_unlock(hdev);
3422 return;
3423 }
3424
3425 hci_dev_lock(hdev);
3426 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3427 hci_dev_unlock(hdev);
3428
3429 switch (hdev->discovery.type) {
3430 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003431 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003432 break;
3433
3434 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003435 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003436 break;
3437
3438 case DISCOV_TYPE_BREDR:
3439 break;
3440
3441 default:
3442 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3443 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003444
3445 if (!timeout)
3446 return;
3447
3448 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003449}
3450
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003451static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003452 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003453{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003454 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003455 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003456 struct hci_cp_le_set_scan_param param_cp;
3457 struct hci_cp_le_set_scan_enable enable_cp;
3458 struct hci_cp_inquiry inq_cp;
3459 struct hci_request req;
3460 /* General inquiry access code (GIAC) */
3461 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003462 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003463 int err;
3464
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003465 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003466
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003467 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003468
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003469 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003470 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003471 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003472 goto failed;
3473 }
3474
Andre Guedes642be6c2012-03-21 00:03:37 -03003475 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3476 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3477 MGMT_STATUS_BUSY);
3478 goto failed;
3479 }
3480
Johan Hedbergff9ef572012-01-04 14:23:45 +02003481 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003483 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003484 goto failed;
3485 }
3486
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003487 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003488 if (!cmd) {
3489 err = -ENOMEM;
3490 goto failed;
3491 }
3492
Andre Guedes4aab14e2012-02-17 20:39:36 -03003493 hdev->discovery.type = cp->type;
3494
Andre Guedes7c307722013-04-30 15:29:28 -03003495 hci_req_init(&req, hdev);
3496
Andre Guedes4aab14e2012-02-17 20:39:36 -03003497 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003498 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003499 status = mgmt_bredr_support(hdev);
3500 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003501 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003502 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003503 mgmt_pending_remove(cmd);
3504 goto failed;
3505 }
3506
Andre Guedes7c307722013-04-30 15:29:28 -03003507 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3508 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3509 MGMT_STATUS_BUSY);
3510 mgmt_pending_remove(cmd);
3511 goto failed;
3512 }
3513
3514 hci_inquiry_cache_flush(hdev);
3515
3516 memset(&inq_cp, 0, sizeof(inq_cp));
3517 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003518 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003519 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003520 break;
3521
3522 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003523 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003524 status = mgmt_le_support(hdev);
3525 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003526 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003527 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003528 mgmt_pending_remove(cmd);
3529 goto failed;
3530 }
3531
Andre Guedes7c307722013-04-30 15:29:28 -03003532 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003533 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003534 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3535 MGMT_STATUS_NOT_SUPPORTED);
3536 mgmt_pending_remove(cmd);
3537 goto failed;
3538 }
3539
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003540 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003541 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3542 MGMT_STATUS_REJECTED);
3543 mgmt_pending_remove(cmd);
3544 goto failed;
3545 }
3546
Andre Guedesc54c3862014-02-26 20:21:50 -03003547 /* If controller is scanning, it means the background scanning
3548 * is running. Thus, we should temporarily stop it in order to
3549 * set the discovery scanning parameters.
3550 */
3551 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3552 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003553
3554 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003555
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003556 /* All active scans will be done with either a resolvable
3557 * private address (when privacy feature has been enabled)
3558 * or unresolvable private address.
3559 */
3560 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003561 if (err < 0) {
3562 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3563 MGMT_STATUS_FAILED);
3564 mgmt_pending_remove(cmd);
3565 goto failed;
3566 }
3567
Andre Guedes7c307722013-04-30 15:29:28 -03003568 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003569 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3570 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003571 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003572 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3573 &param_cp);
3574
3575 memset(&enable_cp, 0, sizeof(enable_cp));
3576 enable_cp.enable = LE_SCAN_ENABLE;
3577 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3578 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3579 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003580 break;
3581
Andre Guedesf39799f2012-02-17 20:39:35 -03003582 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003583 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3584 MGMT_STATUS_INVALID_PARAMS);
3585 mgmt_pending_remove(cmd);
3586 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003587 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003588
Andre Guedes7c307722013-04-30 15:29:28 -03003589 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003590 if (err < 0)
3591 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003592 else
3593 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003594
3595failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003596 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003597 return err;
3598}
3599
Andre Guedes1183fdc2013-04-30 15:29:35 -03003600static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3601{
3602 struct pending_cmd *cmd;
3603 int err;
3604
3605 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3606 if (!cmd)
3607 return -ENOENT;
3608
3609 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3610 &hdev->discovery.type, sizeof(hdev->discovery.type));
3611 mgmt_pending_remove(cmd);
3612
3613 return err;
3614}
3615
Andre Guedes0e05bba2013-04-30 15:29:33 -03003616static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3617{
3618 BT_DBG("status %d", status);
3619
3620 hci_dev_lock(hdev);
3621
3622 if (status) {
3623 mgmt_stop_discovery_failed(hdev, status);
3624 goto unlock;
3625 }
3626
3627 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3628
3629unlock:
3630 hci_dev_unlock(hdev);
3631}
3632
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003633static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003634 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003635{
Johan Hedbergd9306502012-02-20 23:25:18 +02003636 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003637 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003638 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003639 int err;
3640
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003641 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003642
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003643 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003644
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003645 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003646 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003647 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3648 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003649 goto unlock;
3650 }
3651
3652 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003653 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003654 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3655 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003656 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003657 }
3658
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003659 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003660 if (!cmd) {
3661 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003662 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003663 }
3664
Andre Guedes0e05bba2013-04-30 15:29:33 -03003665 hci_req_init(&req, hdev);
3666
Johan Hedberg21a60d32014-06-10 14:05:58 +03003667 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003668
Johan Hedberg21a60d32014-06-10 14:05:58 +03003669 err = hci_req_run(&req, stop_discovery_complete);
3670 if (!err) {
3671 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003672 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003673 }
3674
Johan Hedberg21a60d32014-06-10 14:05:58 +03003675 mgmt_pending_remove(cmd);
3676
3677 /* If no HCI commands were sent we're done */
3678 if (err == -ENODATA) {
3679 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3680 &mgmt_cp->type, sizeof(mgmt_cp->type));
3681 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3682 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003683
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003684unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003685 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003686 return err;
3687}
3688
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003689static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003690 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003691{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003692 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003693 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003694 int err;
3695
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003696 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003697
Johan Hedberg561aafb2012-01-04 13:31:59 +02003698 hci_dev_lock(hdev);
3699
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003700 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003701 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3702 MGMT_STATUS_FAILED, &cp->addr,
3703 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003704 goto failed;
3705 }
3706
Johan Hedberga198e7b2012-02-17 14:27:06 +02003707 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003708 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003709 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3710 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3711 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003712 goto failed;
3713 }
3714
3715 if (cp->name_known) {
3716 e->name_state = NAME_KNOWN;
3717 list_del(&e->list);
3718 } else {
3719 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003720 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003721 }
3722
Johan Hedberge3846622013-01-09 15:29:33 +02003723 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3724 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003725
3726failed:
3727 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003728 return err;
3729}
3730
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003731static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003732 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003733{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003734 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003735 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003736 int err;
3737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003738 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003739
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003740 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003741 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3742 MGMT_STATUS_INVALID_PARAMS,
3743 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003744
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003745 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003746
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003747 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003748 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003749 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003750 else
Szymon Janca6785be2012-12-13 15:11:21 +01003751 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003752
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003753 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003754 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003755
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003756 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003757
3758 return err;
3759}
3760
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003761static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003762 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003763{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003764 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003765 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003766 int err;
3767
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003768 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003769
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003770 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003771 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3772 MGMT_STATUS_INVALID_PARAMS,
3773 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003774
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003775 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003776
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003777 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003778 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003779 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003780 else
Szymon Janca6785be2012-12-13 15:11:21 +01003781 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003782
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003783 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003784 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003785
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003786 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003787
3788 return err;
3789}
3790
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003791static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3792 u16 len)
3793{
3794 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003795 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003796 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003797 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003798
3799 BT_DBG("%s", hdev->name);
3800
Szymon Jancc72d4b82012-03-16 16:02:57 +01003801 source = __le16_to_cpu(cp->source);
3802
3803 if (source > 0x0002)
3804 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3805 MGMT_STATUS_INVALID_PARAMS);
3806
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003807 hci_dev_lock(hdev);
3808
Szymon Jancc72d4b82012-03-16 16:02:57 +01003809 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003810 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3811 hdev->devid_product = __le16_to_cpu(cp->product);
3812 hdev->devid_version = __le16_to_cpu(cp->version);
3813
3814 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3815
Johan Hedberg890ea892013-03-15 17:06:52 -05003816 hci_req_init(&req, hdev);
3817 update_eir(&req);
3818 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003819
3820 hci_dev_unlock(hdev);
3821
3822 return err;
3823}
3824
Johan Hedberg4375f102013-09-25 13:26:10 +03003825static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3826{
3827 struct cmd_lookup match = { NULL, hdev };
3828
3829 if (status) {
3830 u8 mgmt_err = mgmt_status(status);
3831
3832 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3833 cmd_status_rsp, &mgmt_err);
3834 return;
3835 }
3836
3837 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3838 &match);
3839
3840 new_settings(hdev, match.sk);
3841
3842 if (match.sk)
3843 sock_put(match.sk);
3844}
3845
Marcel Holtmann21b51872013-10-10 09:47:53 -07003846static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3847 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003848{
3849 struct mgmt_mode *cp = data;
3850 struct pending_cmd *cmd;
3851 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003852 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003853 int err;
3854
3855 BT_DBG("request for %s", hdev->name);
3856
Johan Hedberge6fe7982013-10-02 15:45:22 +03003857 status = mgmt_le_support(hdev);
3858 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003859 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003860 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003861
3862 if (cp->val != 0x00 && cp->val != 0x01)
3863 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3864 MGMT_STATUS_INVALID_PARAMS);
3865
3866 hci_dev_lock(hdev);
3867
3868 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003869 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003870
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003871 /* The following conditions are ones which mean that we should
3872 * not do any HCI communication but directly send a mgmt
3873 * response to user space (after toggling the flag if
3874 * necessary).
3875 */
3876 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003877 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003878 bool changed = false;
3879
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003880 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3881 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003882 changed = true;
3883 }
3884
3885 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3886 if (err < 0)
3887 goto unlock;
3888
3889 if (changed)
3890 err = new_settings(hdev, sk);
3891
3892 goto unlock;
3893 }
3894
3895 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3896 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3897 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3898 MGMT_STATUS_BUSY);
3899 goto unlock;
3900 }
3901
3902 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3903 if (!cmd) {
3904 err = -ENOMEM;
3905 goto unlock;
3906 }
3907
3908 hci_req_init(&req, hdev);
3909
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003910 if (val)
3911 enable_advertising(&req);
3912 else
3913 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003914
3915 err = hci_req_run(&req, set_advertising_complete);
3916 if (err < 0)
3917 mgmt_pending_remove(cmd);
3918
3919unlock:
3920 hci_dev_unlock(hdev);
3921 return err;
3922}
3923
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003924static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3925 void *data, u16 len)
3926{
3927 struct mgmt_cp_set_static_address *cp = data;
3928 int err;
3929
3930 BT_DBG("%s", hdev->name);
3931
Marcel Holtmann62af4442013-10-02 22:10:32 -07003932 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003933 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003934 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003935
3936 if (hdev_is_powered(hdev))
3937 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3938 MGMT_STATUS_REJECTED);
3939
3940 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3941 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3942 return cmd_status(sk, hdev->id,
3943 MGMT_OP_SET_STATIC_ADDRESS,
3944 MGMT_STATUS_INVALID_PARAMS);
3945
3946 /* Two most significant bits shall be set */
3947 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3948 return cmd_status(sk, hdev->id,
3949 MGMT_OP_SET_STATIC_ADDRESS,
3950 MGMT_STATUS_INVALID_PARAMS);
3951 }
3952
3953 hci_dev_lock(hdev);
3954
3955 bacpy(&hdev->static_addr, &cp->bdaddr);
3956
3957 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3958
3959 hci_dev_unlock(hdev);
3960
3961 return err;
3962}
3963
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003964static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3965 void *data, u16 len)
3966{
3967 struct mgmt_cp_set_scan_params *cp = data;
3968 __u16 interval, window;
3969 int err;
3970
3971 BT_DBG("%s", hdev->name);
3972
3973 if (!lmp_le_capable(hdev))
3974 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3975 MGMT_STATUS_NOT_SUPPORTED);
3976
3977 interval = __le16_to_cpu(cp->interval);
3978
3979 if (interval < 0x0004 || interval > 0x4000)
3980 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3981 MGMT_STATUS_INVALID_PARAMS);
3982
3983 window = __le16_to_cpu(cp->window);
3984
3985 if (window < 0x0004 || window > 0x4000)
3986 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3987 MGMT_STATUS_INVALID_PARAMS);
3988
Marcel Holtmann899e1072013-10-14 09:55:32 -07003989 if (window > interval)
3990 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3991 MGMT_STATUS_INVALID_PARAMS);
3992
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003993 hci_dev_lock(hdev);
3994
3995 hdev->le_scan_interval = interval;
3996 hdev->le_scan_window = window;
3997
3998 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3999
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004000 /* If background scan is running, restart it so new parameters are
4001 * loaded.
4002 */
4003 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4004 hdev->discovery.state == DISCOVERY_STOPPED) {
4005 struct hci_request req;
4006
4007 hci_req_init(&req, hdev);
4008
4009 hci_req_add_le_scan_disable(&req);
4010 hci_req_add_le_passive_scan(&req);
4011
4012 hci_req_run(&req, NULL);
4013 }
4014
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004015 hci_dev_unlock(hdev);
4016
4017 return err;
4018}
4019
Johan Hedberg33e38b32013-03-15 17:07:05 -05004020static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4021{
4022 struct pending_cmd *cmd;
4023
4024 BT_DBG("status 0x%02x", status);
4025
4026 hci_dev_lock(hdev);
4027
4028 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4029 if (!cmd)
4030 goto unlock;
4031
4032 if (status) {
4033 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4034 mgmt_status(status));
4035 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004036 struct mgmt_mode *cp = cmd->param;
4037
4038 if (cp->val)
4039 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4040 else
4041 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4042
Johan Hedberg33e38b32013-03-15 17:07:05 -05004043 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4044 new_settings(hdev, cmd->sk);
4045 }
4046
4047 mgmt_pending_remove(cmd);
4048
4049unlock:
4050 hci_dev_unlock(hdev);
4051}
4052
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004053static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004054 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004055{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004056 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004057 struct pending_cmd *cmd;
4058 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004059 int err;
4060
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004061 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004062
Johan Hedberg56f87902013-10-02 13:43:13 +03004063 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4064 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004065 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4066 MGMT_STATUS_NOT_SUPPORTED);
4067
Johan Hedberga7e80f22013-01-09 16:05:19 +02004068 if (cp->val != 0x00 && cp->val != 0x01)
4069 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4070 MGMT_STATUS_INVALID_PARAMS);
4071
Johan Hedberg5400c042012-02-21 16:40:33 +02004072 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004073 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004074 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004075
4076 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004077 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004078 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004079
4080 hci_dev_lock(hdev);
4081
Johan Hedberg05cbf292013-03-15 17:07:07 -05004082 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4083 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4084 MGMT_STATUS_BUSY);
4085 goto unlock;
4086 }
4087
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004088 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4089 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4090 hdev);
4091 goto unlock;
4092 }
4093
Johan Hedberg33e38b32013-03-15 17:07:05 -05004094 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4095 data, len);
4096 if (!cmd) {
4097 err = -ENOMEM;
4098 goto unlock;
4099 }
4100
4101 hci_req_init(&req, hdev);
4102
Johan Hedberg406d7802013-03-15 17:07:09 -05004103 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004104
4105 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004106 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004107 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004108 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004109 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004110 }
4111
Johan Hedberg33e38b32013-03-15 17:07:05 -05004112unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004113 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004114
Antti Julkuf6422ec2011-06-22 13:11:56 +03004115 return err;
4116}
4117
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004118static void set_bredr_scan(struct hci_request *req)
4119{
4120 struct hci_dev *hdev = req->hdev;
4121 u8 scan = 0;
4122
4123 /* Ensure that fast connectable is disabled. This function will
4124 * not do anything if the page scan parameters are already what
4125 * they should be.
4126 */
4127 write_fast_connectable(req, false);
4128
4129 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4130 scan |= SCAN_PAGE;
4131 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4132 scan |= SCAN_INQUIRY;
4133
4134 if (scan)
4135 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4136}
4137
Johan Hedberg0663ca22013-10-02 13:43:14 +03004138static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4139{
4140 struct pending_cmd *cmd;
4141
4142 BT_DBG("status 0x%02x", status);
4143
4144 hci_dev_lock(hdev);
4145
4146 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4147 if (!cmd)
4148 goto unlock;
4149
4150 if (status) {
4151 u8 mgmt_err = mgmt_status(status);
4152
4153 /* We need to restore the flag if related HCI commands
4154 * failed.
4155 */
4156 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4157
4158 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4159 } else {
4160 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4161 new_settings(hdev, cmd->sk);
4162 }
4163
4164 mgmt_pending_remove(cmd);
4165
4166unlock:
4167 hci_dev_unlock(hdev);
4168}
4169
4170static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4171{
4172 struct mgmt_mode *cp = data;
4173 struct pending_cmd *cmd;
4174 struct hci_request req;
4175 int err;
4176
4177 BT_DBG("request for %s", hdev->name);
4178
4179 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4180 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4181 MGMT_STATUS_NOT_SUPPORTED);
4182
4183 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4184 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4185 MGMT_STATUS_REJECTED);
4186
4187 if (cp->val != 0x00 && cp->val != 0x01)
4188 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4189 MGMT_STATUS_INVALID_PARAMS);
4190
4191 hci_dev_lock(hdev);
4192
4193 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4194 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4195 goto unlock;
4196 }
4197
4198 if (!hdev_is_powered(hdev)) {
4199 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004200 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4201 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4202 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4203 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4204 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4205 }
4206
4207 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4208
4209 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4210 if (err < 0)
4211 goto unlock;
4212
4213 err = new_settings(hdev, sk);
4214 goto unlock;
4215 }
4216
4217 /* Reject disabling when powered on */
4218 if (!cp->val) {
4219 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4220 MGMT_STATUS_REJECTED);
4221 goto unlock;
4222 }
4223
4224 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4225 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4226 MGMT_STATUS_BUSY);
4227 goto unlock;
4228 }
4229
4230 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4231 if (!cmd) {
4232 err = -ENOMEM;
4233 goto unlock;
4234 }
4235
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004236 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004237 * generates the correct flags.
4238 */
4239 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4240
4241 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004242
4243 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4244 set_bredr_scan(&req);
4245
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004246 /* Since only the advertising data flags will change, there
4247 * is no need to update the scan response data.
4248 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004249 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004250
Johan Hedberg0663ca22013-10-02 13:43:14 +03004251 err = hci_req_run(&req, set_bredr_complete);
4252 if (err < 0)
4253 mgmt_pending_remove(cmd);
4254
4255unlock:
4256 hci_dev_unlock(hdev);
4257 return err;
4258}
4259
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004260static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4261 void *data, u16 len)
4262{
4263 struct mgmt_mode *cp = data;
4264 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004265 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004266 int err;
4267
4268 BT_DBG("request for %s", hdev->name);
4269
4270 status = mgmt_bredr_support(hdev);
4271 if (status)
4272 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4273 status);
4274
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004275 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004276 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004277 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4278 MGMT_STATUS_NOT_SUPPORTED);
4279
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004280 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004281 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4282 MGMT_STATUS_INVALID_PARAMS);
4283
4284 hci_dev_lock(hdev);
4285
4286 if (!hdev_is_powered(hdev)) {
4287 bool changed;
4288
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004289 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004290 changed = !test_and_set_bit(HCI_SC_ENABLED,
4291 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004292 if (cp->val == 0x02)
4293 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4294 else
4295 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4296 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004297 changed = test_and_clear_bit(HCI_SC_ENABLED,
4298 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004299 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4300 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004301
4302 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4303 if (err < 0)
4304 goto failed;
4305
4306 if (changed)
4307 err = new_settings(hdev, sk);
4308
4309 goto failed;
4310 }
4311
4312 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4313 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4314 MGMT_STATUS_BUSY);
4315 goto failed;
4316 }
4317
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004318 val = !!cp->val;
4319
4320 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4321 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004322 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4323 goto failed;
4324 }
4325
4326 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4327 if (!cmd) {
4328 err = -ENOMEM;
4329 goto failed;
4330 }
4331
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004332 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004333 if (err < 0) {
4334 mgmt_pending_remove(cmd);
4335 goto failed;
4336 }
4337
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004338 if (cp->val == 0x02)
4339 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4340 else
4341 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4342
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004343failed:
4344 hci_dev_unlock(hdev);
4345 return err;
4346}
4347
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004348static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4349 void *data, u16 len)
4350{
4351 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004352 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004353 int err;
4354
4355 BT_DBG("request for %s", hdev->name);
4356
Johan Hedbergb97109792014-06-24 14:00:28 +03004357 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004358 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4359 MGMT_STATUS_INVALID_PARAMS);
4360
4361 hci_dev_lock(hdev);
4362
4363 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004364 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4365 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004366 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004367 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4368 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004369
Johan Hedbergb97109792014-06-24 14:00:28 +03004370 if (cp->val == 0x02)
4371 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4372 &hdev->dev_flags);
4373 else
4374 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4375 &hdev->dev_flags);
4376
4377 if (hdev_is_powered(hdev) && use_changed &&
4378 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4379 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4380 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4381 sizeof(mode), &mode);
4382 }
4383
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004384 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4385 if (err < 0)
4386 goto unlock;
4387
4388 if (changed)
4389 err = new_settings(hdev, sk);
4390
4391unlock:
4392 hci_dev_unlock(hdev);
4393 return err;
4394}
4395
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004396static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4397 u16 len)
4398{
4399 struct mgmt_cp_set_privacy *cp = cp_data;
4400 bool changed;
4401 int err;
4402
4403 BT_DBG("request for %s", hdev->name);
4404
4405 if (!lmp_le_capable(hdev))
4406 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4407 MGMT_STATUS_NOT_SUPPORTED);
4408
4409 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4410 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4411 MGMT_STATUS_INVALID_PARAMS);
4412
4413 if (hdev_is_powered(hdev))
4414 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4415 MGMT_STATUS_REJECTED);
4416
4417 hci_dev_lock(hdev);
4418
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004419 /* If user space supports this command it is also expected to
4420 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4421 */
4422 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4423
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004424 if (cp->privacy) {
4425 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4426 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4427 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4428 } else {
4429 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4430 memset(hdev->irk, 0, sizeof(hdev->irk));
4431 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4432 }
4433
4434 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4435 if (err < 0)
4436 goto unlock;
4437
4438 if (changed)
4439 err = new_settings(hdev, sk);
4440
4441unlock:
4442 hci_dev_unlock(hdev);
4443 return err;
4444}
4445
Johan Hedberg41edf162014-02-18 10:19:35 +02004446static bool irk_is_valid(struct mgmt_irk_info *irk)
4447{
4448 switch (irk->addr.type) {
4449 case BDADDR_LE_PUBLIC:
4450 return true;
4451
4452 case BDADDR_LE_RANDOM:
4453 /* Two most significant bits shall be set */
4454 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4455 return false;
4456 return true;
4457 }
4458
4459 return false;
4460}
4461
4462static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4463 u16 len)
4464{
4465 struct mgmt_cp_load_irks *cp = cp_data;
4466 u16 irk_count, expected_len;
4467 int i, err;
4468
4469 BT_DBG("request for %s", hdev->name);
4470
4471 if (!lmp_le_capable(hdev))
4472 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4473 MGMT_STATUS_NOT_SUPPORTED);
4474
4475 irk_count = __le16_to_cpu(cp->irk_count);
4476
4477 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4478 if (expected_len != len) {
4479 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004480 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004481 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4482 MGMT_STATUS_INVALID_PARAMS);
4483 }
4484
4485 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4486
4487 for (i = 0; i < irk_count; i++) {
4488 struct mgmt_irk_info *key = &cp->irks[i];
4489
4490 if (!irk_is_valid(key))
4491 return cmd_status(sk, hdev->id,
4492 MGMT_OP_LOAD_IRKS,
4493 MGMT_STATUS_INVALID_PARAMS);
4494 }
4495
4496 hci_dev_lock(hdev);
4497
4498 hci_smp_irks_clear(hdev);
4499
4500 for (i = 0; i < irk_count; i++) {
4501 struct mgmt_irk_info *irk = &cp->irks[i];
4502 u8 addr_type;
4503
4504 if (irk->addr.type == BDADDR_LE_PUBLIC)
4505 addr_type = ADDR_LE_DEV_PUBLIC;
4506 else
4507 addr_type = ADDR_LE_DEV_RANDOM;
4508
4509 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4510 BDADDR_ANY);
4511 }
4512
4513 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4514
4515 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4516
4517 hci_dev_unlock(hdev);
4518
4519 return err;
4520}
4521
Johan Hedberg3f706b72013-01-20 14:27:16 +02004522static bool ltk_is_valid(struct mgmt_ltk_info *key)
4523{
4524 if (key->master != 0x00 && key->master != 0x01)
4525 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004526
4527 switch (key->addr.type) {
4528 case BDADDR_LE_PUBLIC:
4529 return true;
4530
4531 case BDADDR_LE_RANDOM:
4532 /* Two most significant bits shall be set */
4533 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4534 return false;
4535 return true;
4536 }
4537
4538 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004539}
4540
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004541static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004542 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004543{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004544 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4545 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004546 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004547
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004548 BT_DBG("request for %s", hdev->name);
4549
4550 if (!lmp_le_capable(hdev))
4551 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4552 MGMT_STATUS_NOT_SUPPORTED);
4553
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004554 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004555
4556 expected_len = sizeof(*cp) + key_count *
4557 sizeof(struct mgmt_ltk_info);
4558 if (expected_len != len) {
4559 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004560 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004561 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004562 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004563 }
4564
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004565 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004566
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004567 for (i = 0; i < key_count; i++) {
4568 struct mgmt_ltk_info *key = &cp->keys[i];
4569
Johan Hedberg3f706b72013-01-20 14:27:16 +02004570 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004571 return cmd_status(sk, hdev->id,
4572 MGMT_OP_LOAD_LONG_TERM_KEYS,
4573 MGMT_STATUS_INVALID_PARAMS);
4574 }
4575
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004576 hci_dev_lock(hdev);
4577
4578 hci_smp_ltks_clear(hdev);
4579
4580 for (i = 0; i < key_count; i++) {
4581 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004582 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004583
4584 if (key->addr.type == BDADDR_LE_PUBLIC)
4585 addr_type = ADDR_LE_DEV_PUBLIC;
4586 else
4587 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004588
4589 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004590 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004591 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004592 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004593
Johan Hedberg61b43352014-05-29 19:36:53 +03004594 switch (key->type) {
4595 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004596 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004597 break;
4598 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004599 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004600 break;
4601 default:
4602 continue;
4603 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004604
Johan Hedberg35d70272014-02-19 14:57:47 +02004605 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004606 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004607 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004608 }
4609
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004610 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4611 NULL, 0);
4612
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004613 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004614
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004615 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004616}
4617
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004618struct cmd_conn_lookup {
4619 struct hci_conn *conn;
4620 bool valid_tx_power;
4621 u8 mgmt_status;
4622};
4623
4624static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4625{
4626 struct cmd_conn_lookup *match = data;
4627 struct mgmt_cp_get_conn_info *cp;
4628 struct mgmt_rp_get_conn_info rp;
4629 struct hci_conn *conn = cmd->user_data;
4630
4631 if (conn != match->conn)
4632 return;
4633
4634 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4635
4636 memset(&rp, 0, sizeof(rp));
4637 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4638 rp.addr.type = cp->addr.type;
4639
4640 if (!match->mgmt_status) {
4641 rp.rssi = conn->rssi;
4642
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004643 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004644 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004645 rp.max_tx_power = conn->max_tx_power;
4646 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004647 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004648 rp.max_tx_power = HCI_TX_POWER_INVALID;
4649 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004650 }
4651
4652 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4653 match->mgmt_status, &rp, sizeof(rp));
4654
4655 hci_conn_drop(conn);
4656
4657 mgmt_pending_remove(cmd);
4658}
4659
4660static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4661{
4662 struct hci_cp_read_rssi *cp;
4663 struct hci_conn *conn;
4664 struct cmd_conn_lookup match;
4665 u16 handle;
4666
4667 BT_DBG("status 0x%02x", status);
4668
4669 hci_dev_lock(hdev);
4670
4671 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004672 * otherwise we assume it's not valid. At the moment we assume that
4673 * either both or none of current and max values are valid to keep code
4674 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004675 */
4676 match.valid_tx_power = !status;
4677
4678 /* Commands sent in request are either Read RSSI or Read Transmit Power
4679 * Level so we check which one was last sent to retrieve connection
4680 * handle. Both commands have handle as first parameter so it's safe to
4681 * cast data on the same command struct.
4682 *
4683 * First command sent is always Read RSSI and we fail only if it fails.
4684 * In other case we simply override error to indicate success as we
4685 * already remembered if TX power value is actually valid.
4686 */
4687 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4688 if (!cp) {
4689 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4690 status = 0;
4691 }
4692
4693 if (!cp) {
4694 BT_ERR("invalid sent_cmd in response");
4695 goto unlock;
4696 }
4697
4698 handle = __le16_to_cpu(cp->handle);
4699 conn = hci_conn_hash_lookup_handle(hdev, handle);
4700 if (!conn) {
4701 BT_ERR("unknown handle (%d) in response", handle);
4702 goto unlock;
4703 }
4704
4705 match.conn = conn;
4706 match.mgmt_status = mgmt_status(status);
4707
4708 /* Cache refresh is complete, now reply for mgmt request for given
4709 * connection only.
4710 */
4711 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4712 get_conn_info_complete, &match);
4713
4714unlock:
4715 hci_dev_unlock(hdev);
4716}
4717
4718static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4719 u16 len)
4720{
4721 struct mgmt_cp_get_conn_info *cp = data;
4722 struct mgmt_rp_get_conn_info rp;
4723 struct hci_conn *conn;
4724 unsigned long conn_info_age;
4725 int err = 0;
4726
4727 BT_DBG("%s", hdev->name);
4728
4729 memset(&rp, 0, sizeof(rp));
4730 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4731 rp.addr.type = cp->addr.type;
4732
4733 if (!bdaddr_type_is_valid(cp->addr.type))
4734 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4735 MGMT_STATUS_INVALID_PARAMS,
4736 &rp, sizeof(rp));
4737
4738 hci_dev_lock(hdev);
4739
4740 if (!hdev_is_powered(hdev)) {
4741 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4742 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4743 goto unlock;
4744 }
4745
4746 if (cp->addr.type == BDADDR_BREDR)
4747 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4748 &cp->addr.bdaddr);
4749 else
4750 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4751
4752 if (!conn || conn->state != BT_CONNECTED) {
4753 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4754 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4755 goto unlock;
4756 }
4757
4758 /* To avoid client trying to guess when to poll again for information we
4759 * calculate conn info age as random value between min/max set in hdev.
4760 */
4761 conn_info_age = hdev->conn_info_min_age +
4762 prandom_u32_max(hdev->conn_info_max_age -
4763 hdev->conn_info_min_age);
4764
4765 /* Query controller to refresh cached values if they are too old or were
4766 * never read.
4767 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004768 if (time_after(jiffies, conn->conn_info_timestamp +
4769 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004770 !conn->conn_info_timestamp) {
4771 struct hci_request req;
4772 struct hci_cp_read_tx_power req_txp_cp;
4773 struct hci_cp_read_rssi req_rssi_cp;
4774 struct pending_cmd *cmd;
4775
4776 hci_req_init(&req, hdev);
4777 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4778 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4779 &req_rssi_cp);
4780
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004781 /* For LE links TX power does not change thus we don't need to
4782 * query for it once value is known.
4783 */
4784 if (!bdaddr_type_is_le(cp->addr.type) ||
4785 conn->tx_power == HCI_TX_POWER_INVALID) {
4786 req_txp_cp.handle = cpu_to_le16(conn->handle);
4787 req_txp_cp.type = 0x00;
4788 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4789 sizeof(req_txp_cp), &req_txp_cp);
4790 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004791
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004792 /* Max TX power needs to be read only once per connection */
4793 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4794 req_txp_cp.handle = cpu_to_le16(conn->handle);
4795 req_txp_cp.type = 0x01;
4796 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4797 sizeof(req_txp_cp), &req_txp_cp);
4798 }
4799
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004800 err = hci_req_run(&req, conn_info_refresh_complete);
4801 if (err < 0)
4802 goto unlock;
4803
4804 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4805 data, len);
4806 if (!cmd) {
4807 err = -ENOMEM;
4808 goto unlock;
4809 }
4810
4811 hci_conn_hold(conn);
4812 cmd->user_data = conn;
4813
4814 conn->conn_info_timestamp = jiffies;
4815 } else {
4816 /* Cache is valid, just reply with values cached in hci_conn */
4817 rp.rssi = conn->rssi;
4818 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004819 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004820
4821 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4822 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4823 }
4824
4825unlock:
4826 hci_dev_unlock(hdev);
4827 return err;
4828}
4829
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004830static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004831 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4832 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004833 bool var_len;
4834 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004835} mgmt_handlers[] = {
4836 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004837 { read_version, false, MGMT_READ_VERSION_SIZE },
4838 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4839 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4840 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4841 { set_powered, false, MGMT_SETTING_SIZE },
4842 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4843 { set_connectable, false, MGMT_SETTING_SIZE },
4844 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4845 { set_pairable, false, MGMT_SETTING_SIZE },
4846 { set_link_security, false, MGMT_SETTING_SIZE },
4847 { set_ssp, false, MGMT_SETTING_SIZE },
4848 { set_hs, false, MGMT_SETTING_SIZE },
4849 { set_le, false, MGMT_SETTING_SIZE },
4850 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4851 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4852 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4853 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4854 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4855 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4856 { disconnect, false, MGMT_DISCONNECT_SIZE },
4857 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4858 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4859 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4860 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4861 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4862 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4863 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4864 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4865 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4866 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4867 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4868 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004869 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004870 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4871 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4872 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4873 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4874 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4875 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004876 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004877 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004878 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004879 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004880 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004881 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004882 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004883 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004884 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004885 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004886};
4887
4888
Johan Hedberg03811012010-12-08 00:21:06 +02004889int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4890{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004891 void *buf;
4892 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004893 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004894 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004895 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004896 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004897 int err;
4898
4899 BT_DBG("got %zu bytes", msglen);
4900
4901 if (msglen < sizeof(*hdr))
4902 return -EINVAL;
4903
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004904 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004905 if (!buf)
4906 return -ENOMEM;
4907
4908 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4909 err = -EFAULT;
4910 goto done;
4911 }
4912
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004913 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004914 opcode = __le16_to_cpu(hdr->opcode);
4915 index = __le16_to_cpu(hdr->index);
4916 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004917
4918 if (len != msglen - sizeof(*hdr)) {
4919 err = -EINVAL;
4920 goto done;
4921 }
4922
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004923 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004924 hdev = hci_dev_get(index);
4925 if (!hdev) {
4926 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004927 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004928 goto done;
4929 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004930
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004931 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4932 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004933 err = cmd_status(sk, index, opcode,
4934 MGMT_STATUS_INVALID_INDEX);
4935 goto done;
4936 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004937 }
4938
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004939 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004940 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004941 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004942 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004943 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004944 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004945 }
4946
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004947 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004948 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004949 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004950 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004951 goto done;
4952 }
4953
Johan Hedbergbe22b542012-03-01 22:24:41 +02004954 handler = &mgmt_handlers[opcode];
4955
4956 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004957 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004958 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004959 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004960 goto done;
4961 }
4962
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004963 if (hdev)
4964 mgmt_init_hdev(sk, hdev);
4965
4966 cp = buf + sizeof(*hdr);
4967
Johan Hedbergbe22b542012-03-01 22:24:41 +02004968 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004969 if (err < 0)
4970 goto done;
4971
Johan Hedberg03811012010-12-08 00:21:06 +02004972 err = msglen;
4973
4974done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004975 if (hdev)
4976 hci_dev_put(hdev);
4977
Johan Hedberg03811012010-12-08 00:21:06 +02004978 kfree(buf);
4979 return err;
4980}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004981
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004982void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004983{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004984 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004985 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004986
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004987 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004988}
4989
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004990void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004991{
Johan Hedberg5f159032012-03-02 03:13:19 +02004992 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004993
Marcel Holtmann1514b892013-10-06 08:25:01 -07004994 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004995 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004996
Johan Hedberg744cf192011-11-08 20:40:14 +02004997 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004998
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004999 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005000}
5001
Andre Guedes6046dc32014-02-26 20:21:51 -03005002/* This function requires the caller holds hdev->lock */
5003static void restart_le_auto_conns(struct hci_dev *hdev)
5004{
5005 struct hci_conn_params *p;
5006
5007 list_for_each_entry(p, &hdev->le_conn_params, list) {
5008 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
5009 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
5010 }
5011}
5012
Johan Hedberg229ab392013-03-15 17:06:53 -05005013static void powered_complete(struct hci_dev *hdev, u8 status)
5014{
5015 struct cmd_lookup match = { NULL, hdev };
5016
5017 BT_DBG("status 0x%02x", status);
5018
5019 hci_dev_lock(hdev);
5020
Andre Guedes6046dc32014-02-26 20:21:51 -03005021 restart_le_auto_conns(hdev);
5022
Johan Hedberg229ab392013-03-15 17:06:53 -05005023 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5024
5025 new_settings(hdev, match.sk);
5026
5027 hci_dev_unlock(hdev);
5028
5029 if (match.sk)
5030 sock_put(match.sk);
5031}
5032
Johan Hedberg70da6242013-03-15 17:06:51 -05005033static int powered_update_hci(struct hci_dev *hdev)
5034{
Johan Hedberg890ea892013-03-15 17:06:52 -05005035 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005036 u8 link_sec;
5037
Johan Hedberg890ea892013-03-15 17:06:52 -05005038 hci_req_init(&req, hdev);
5039
Johan Hedberg70da6242013-03-15 17:06:51 -05005040 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5041 !lmp_host_ssp_capable(hdev)) {
5042 u8 ssp = 1;
5043
Johan Hedberg890ea892013-03-15 17:06:52 -05005044 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005045 }
5046
Johan Hedbergc73eee92013-04-19 18:35:21 +03005047 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5048 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005049 struct hci_cp_write_le_host_supported cp;
5050
5051 cp.le = 1;
5052 cp.simul = lmp_le_br_capable(hdev);
5053
5054 /* Check first if we already have the right
5055 * host state (host features set)
5056 */
5057 if (cp.le != lmp_host_le_capable(hdev) ||
5058 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005059 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5060 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005061 }
5062
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005063 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005064 /* Make sure the controller has a good default for
5065 * advertising data. This also applies to the case
5066 * where BR/EDR was toggled during the AUTO_OFF phase.
5067 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005068 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005069 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005070 update_scan_rsp_data(&req);
5071 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005072
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005073 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5074 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005075 }
5076
Johan Hedberg70da6242013-03-15 17:06:51 -05005077 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5078 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005079 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5080 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005081
5082 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005083 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5084 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005085 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005086 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005087 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005088 }
5089
Johan Hedberg229ab392013-03-15 17:06:53 -05005090 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005091}
5092
Johan Hedberg744cf192011-11-08 20:40:14 +02005093int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005094{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005095 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005096 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5097 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005098 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005099
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005100 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5101 return 0;
5102
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005103 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005104 if (powered_update_hci(hdev) == 0)
5105 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005106
Johan Hedberg229ab392013-03-15 17:06:53 -05005107 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5108 &match);
5109 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005110 }
5111
Johan Hedberg229ab392013-03-15 17:06:53 -05005112 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5113 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5114
5115 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5116 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5117 zero_cod, sizeof(zero_cod), NULL);
5118
5119new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005120 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005121
5122 if (match.sk)
5123 sock_put(match.sk);
5124
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005125 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005126}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005127
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005128void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005129{
5130 struct pending_cmd *cmd;
5131 u8 status;
5132
5133 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5134 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005135 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005136
5137 if (err == -ERFKILL)
5138 status = MGMT_STATUS_RFKILLED;
5139 else
5140 status = MGMT_STATUS_FAILED;
5141
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005142 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005143
5144 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005145}
5146
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005147void mgmt_discoverable_timeout(struct hci_dev *hdev)
5148{
5149 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005150
5151 hci_dev_lock(hdev);
5152
5153 /* When discoverable timeout triggers, then just make sure
5154 * the limited discoverable flag is cleared. Even in the case
5155 * of a timeout triggered from general discoverable, it is
5156 * safe to unconditionally clear the flag.
5157 */
5158 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005159 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005160
5161 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005162 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5163 u8 scan = SCAN_PAGE;
5164 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5165 sizeof(scan), &scan);
5166 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005167 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005168 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005169 hci_req_run(&req, NULL);
5170
5171 hdev->discov_timeout = 0;
5172
Johan Hedberg9a43e252013-10-20 19:00:07 +03005173 new_settings(hdev, NULL);
5174
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005175 hci_dev_unlock(hdev);
5176}
5177
Marcel Holtmann86a75642013-10-15 06:33:54 -07005178void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005179{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005180 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005181
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005182 /* Nothing needed here if there's a pending command since that
5183 * commands request completion callback takes care of everything
5184 * necessary.
5185 */
5186 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005187 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005188
Johan Hedbergbd107992014-02-24 14:52:19 +02005189 /* Powering off may clear the scan mode - don't let that interfere */
5190 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5191 return;
5192
Johan Hedberg9a43e252013-10-20 19:00:07 +03005193 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005194 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005195 } else {
5196 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005197 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005198 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005199
Johan Hedberg9a43e252013-10-20 19:00:07 +03005200 if (changed) {
5201 struct hci_request req;
5202
5203 /* In case this change in discoverable was triggered by
5204 * a disabling of connectable there could be a need to
5205 * update the advertising flags.
5206 */
5207 hci_req_init(&req, hdev);
5208 update_adv_data(&req);
5209 hci_req_run(&req, NULL);
5210
Marcel Holtmann86a75642013-10-15 06:33:54 -07005211 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005212 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005213}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005214
Marcel Holtmanna3309162013-10-15 06:33:55 -07005215void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005216{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005217 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005218
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005219 /* Nothing needed here if there's a pending command since that
5220 * commands request completion callback takes care of everything
5221 * necessary.
5222 */
5223 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005224 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005225
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005226 /* Powering off may clear the scan mode - don't let that interfere */
5227 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5228 return;
5229
Marcel Holtmanna3309162013-10-15 06:33:55 -07005230 if (connectable)
5231 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5232 else
5233 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005234
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005235 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005236 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005237}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005238
Johan Hedberg778b2352014-02-24 14:52:17 +02005239void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5240{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005241 /* Powering off may stop advertising - don't let that interfere */
5242 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5243 return;
5244
Johan Hedberg778b2352014-02-24 14:52:17 +02005245 if (advertising)
5246 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5247 else
5248 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5249}
5250
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005251void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005252{
Johan Hedbergca69b792011-11-11 18:10:00 +02005253 u8 mgmt_err = mgmt_status(status);
5254
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005255 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005256 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005257 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005258
5259 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005260 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005261 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005262}
5263
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005264void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5265 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005266{
Johan Hedberg86742e12011-11-07 23:13:38 +02005267 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005268
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005269 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005270
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005271 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005272 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005273 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005274 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005275 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005276 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005277
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005278 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005279}
Johan Hedbergf7520542011-01-20 12:34:39 +02005280
Johan Hedbergd7b25452014-05-23 13:19:53 +03005281static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5282{
5283 if (ltk->authenticated)
5284 return MGMT_LTK_AUTHENTICATED;
5285
5286 return MGMT_LTK_UNAUTHENTICATED;
5287}
5288
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005289void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005290{
5291 struct mgmt_ev_new_long_term_key ev;
5292
5293 memset(&ev, 0, sizeof(ev));
5294
Marcel Holtmann5192d302014-02-19 17:11:58 -08005295 /* Devices using resolvable or non-resolvable random addresses
5296 * without providing an indentity resolving key don't require
5297 * to store long term keys. Their addresses will change the
5298 * next time around.
5299 *
5300 * Only when a remote device provides an identity address
5301 * make sure the long term key is stored. If the remote
5302 * identity is known, the long term keys are internally
5303 * mapped to the identity address. So allow static random
5304 * and public addresses here.
5305 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005306 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5307 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5308 ev.store_hint = 0x00;
5309 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005310 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005311
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005312 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005313 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005314 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005315 ev.key.enc_size = key->enc_size;
5316 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005317 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005318
Johan Hedberg2ceba532014-06-16 19:25:16 +03005319 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005320 ev.key.master = 1;
5321
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005322 memcpy(ev.key.val, key->val, sizeof(key->val));
5323
Marcel Holtmann083368f2013-10-15 14:26:29 -07005324 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005325}
5326
Johan Hedberg95fbac82014-02-19 15:18:31 +02005327void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5328{
5329 struct mgmt_ev_new_irk ev;
5330
5331 memset(&ev, 0, sizeof(ev));
5332
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005333 /* For identity resolving keys from devices that are already
5334 * using a public address or static random address, do not
5335 * ask for storing this key. The identity resolving key really
5336 * is only mandatory for devices using resovlable random
5337 * addresses.
5338 *
5339 * Storing all identity resolving keys has the downside that
5340 * they will be also loaded on next boot of they system. More
5341 * identity resolving keys, means more time during scanning is
5342 * needed to actually resolve these addresses.
5343 */
5344 if (bacmp(&irk->rpa, BDADDR_ANY))
5345 ev.store_hint = 0x01;
5346 else
5347 ev.store_hint = 0x00;
5348
Johan Hedberg95fbac82014-02-19 15:18:31 +02005349 bacpy(&ev.rpa, &irk->rpa);
5350 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5351 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5352 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5353
5354 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5355}
5356
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005357void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5358 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005359{
5360 struct mgmt_ev_new_csrk ev;
5361
5362 memset(&ev, 0, sizeof(ev));
5363
5364 /* Devices using resolvable or non-resolvable random addresses
5365 * without providing an indentity resolving key don't require
5366 * to store signature resolving keys. Their addresses will change
5367 * the next time around.
5368 *
5369 * Only when a remote device provides an identity address
5370 * make sure the signature resolving key is stored. So allow
5371 * static random and public addresses here.
5372 */
5373 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5374 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5375 ev.store_hint = 0x00;
5376 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005377 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005378
5379 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5380 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5381 ev.key.master = csrk->master;
5382 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5383
5384 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5385}
5386
Marcel Holtmann94933992013-10-15 10:26:39 -07005387static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5388 u8 data_len)
5389{
5390 eir[eir_len++] = sizeof(type) + data_len;
5391 eir[eir_len++] = type;
5392 memcpy(&eir[eir_len], data, data_len);
5393 eir_len += data_len;
5394
5395 return eir_len;
5396}
5397
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005398void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5399 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5400 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005401{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005402 char buf[512];
5403 struct mgmt_ev_device_connected *ev = (void *) buf;
5404 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005405
Johan Hedbergb644ba32012-01-17 21:48:47 +02005406 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005407 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005408
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005409 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005410
Johan Hedbergb644ba32012-01-17 21:48:47 +02005411 if (name_len > 0)
5412 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005413 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005414
5415 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005416 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005417 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005418
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005419 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005420
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005421 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5422 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005423}
5424
Johan Hedberg8962ee72011-01-20 12:40:27 +02005425static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5426{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005427 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005428 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005429 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005430
Johan Hedberg88c3df12012-02-09 14:27:38 +02005431 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5432 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005433
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005434 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005435 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005436
5437 *sk = cmd->sk;
5438 sock_hold(*sk);
5439
Johan Hedberga664b5b2011-02-19 12:06:02 -03005440 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005441}
5442
Johan Hedberg124f6e32012-02-09 13:50:12 +02005443static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005444{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005445 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005446 struct mgmt_cp_unpair_device *cp = cmd->param;
5447 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005448
5449 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005450 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5451 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005452
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005453 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5454
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005455 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005456
5457 mgmt_pending_remove(cmd);
5458}
5459
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005460void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005461 u8 link_type, u8 addr_type, u8 reason,
5462 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005463{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005464 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005465 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005466 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005467
Johan Hedberg8b064a32014-02-24 14:52:22 +02005468 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5469 if (power_off) {
5470 struct mgmt_mode *cp = power_off->param;
5471
5472 /* The connection is still in hci_conn_hash so test for 1
5473 * instead of 0 to know if this is the last one.
5474 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005475 if (!cp->val && hci_conn_count(hdev) == 1) {
5476 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005477 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005478 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005479 }
5480
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005481 if (!mgmt_connected)
5482 return;
5483
Andre Guedes57eb7762013-10-30 19:01:41 -03005484 if (link_type != ACL_LINK && link_type != LE_LINK)
5485 return;
5486
Johan Hedberg744cf192011-11-08 20:40:14 +02005487 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005488
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005489 bacpy(&ev.addr.bdaddr, bdaddr);
5490 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5491 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005492
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005493 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005494
5495 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005496 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005497
Johan Hedberg124f6e32012-02-09 13:50:12 +02005498 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005499 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005500}
5501
Marcel Holtmann78929242013-10-06 23:55:47 -07005502void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5503 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005504{
Andre Guedes3655bba2013-10-30 19:01:40 -03005505 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5506 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005507 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005508 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005509
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005510 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5511 hdev);
5512
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005513 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005514 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005515 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005516
Andre Guedes3655bba2013-10-30 19:01:40 -03005517 cp = cmd->param;
5518
5519 if (bacmp(bdaddr, &cp->addr.bdaddr))
5520 return;
5521
5522 if (cp->addr.type != bdaddr_type)
5523 return;
5524
Johan Hedberg88c3df12012-02-09 14:27:38 +02005525 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005526 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005527
Marcel Holtmann78929242013-10-06 23:55:47 -07005528 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5529 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005530
Johan Hedberga664b5b2011-02-19 12:06:02 -03005531 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005532}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005533
Marcel Holtmann445608d2013-10-06 23:55:48 -07005534void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5535 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005536{
5537 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005538 struct pending_cmd *power_off;
5539
5540 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5541 if (power_off) {
5542 struct mgmt_mode *cp = power_off->param;
5543
5544 /* The connection is still in hci_conn_hash so test for 1
5545 * instead of 0 to know if this is the last one.
5546 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005547 if (!cp->val && hci_conn_count(hdev) == 1) {
5548 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005549 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005550 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005551 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005552
Johan Hedberg4c659c32011-11-07 23:13:39 +02005553 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005554 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005555 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005556
Marcel Holtmann445608d2013-10-06 23:55:48 -07005557 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005558}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005559
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005560void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005561{
5562 struct mgmt_ev_pin_code_request ev;
5563
Johan Hedbergd8457692012-02-17 14:24:57 +02005564 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005565 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005566 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005567
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005568 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005569}
5570
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005571void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5572 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005573{
5574 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005575 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005576
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005577 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005578 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005579 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005580
Johan Hedbergd8457692012-02-17 14:24:57 +02005581 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005582 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005583
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005584 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5585 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005586
Johan Hedberga664b5b2011-02-19 12:06:02 -03005587 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005588}
5589
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005590void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5591 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005592{
5593 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005594 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005595
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005596 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005597 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005598 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005599
Johan Hedbergd8457692012-02-17 14:24:57 +02005600 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005601 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005602
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005603 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5604 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005605
Johan Hedberga664b5b2011-02-19 12:06:02 -03005606 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005607}
Johan Hedberga5c29682011-02-19 12:05:57 -03005608
Johan Hedberg744cf192011-11-08 20:40:14 +02005609int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005610 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005611 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005612{
5613 struct mgmt_ev_user_confirm_request ev;
5614
Johan Hedberg744cf192011-11-08 20:40:14 +02005615 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005616
Johan Hedberg272d90d2012-02-09 15:26:12 +02005617 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005618 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005619 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005620 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005621
Johan Hedberg744cf192011-11-08 20:40:14 +02005622 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005623 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005624}
5625
Johan Hedberg272d90d2012-02-09 15:26:12 +02005626int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005627 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005628{
5629 struct mgmt_ev_user_passkey_request ev;
5630
5631 BT_DBG("%s", hdev->name);
5632
Johan Hedberg272d90d2012-02-09 15:26:12 +02005633 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005634 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005635
5636 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005637 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005638}
5639
Brian Gix0df4c182011-11-16 13:53:13 -08005640static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005641 u8 link_type, u8 addr_type, u8 status,
5642 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005643{
5644 struct pending_cmd *cmd;
5645 struct mgmt_rp_user_confirm_reply rp;
5646 int err;
5647
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005648 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005649 if (!cmd)
5650 return -ENOENT;
5651
Johan Hedberg272d90d2012-02-09 15:26:12 +02005652 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005653 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005654 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005655 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005656
Johan Hedberga664b5b2011-02-19 12:06:02 -03005657 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005658
5659 return err;
5660}
5661
Johan Hedberg744cf192011-11-08 20:40:14 +02005662int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005663 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005664{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005665 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005666 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005667}
5668
Johan Hedberg272d90d2012-02-09 15:26:12 +02005669int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005670 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005671{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005672 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005673 status,
5674 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005675}
Johan Hedberg2a611692011-02-19 12:06:00 -03005676
Brian Gix604086b2011-11-23 08:28:33 -08005677int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005678 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005679{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005680 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005681 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005682}
5683
Johan Hedberg272d90d2012-02-09 15:26:12 +02005684int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005685 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005686{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005687 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005688 status,
5689 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005690}
5691
Johan Hedberg92a25252012-09-06 18:39:26 +03005692int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5693 u8 link_type, u8 addr_type, u32 passkey,
5694 u8 entered)
5695{
5696 struct mgmt_ev_passkey_notify ev;
5697
5698 BT_DBG("%s", hdev->name);
5699
5700 bacpy(&ev.addr.bdaddr, bdaddr);
5701 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5702 ev.passkey = __cpu_to_le32(passkey);
5703 ev.entered = entered;
5704
5705 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5706}
5707
Marcel Holtmanne5460992013-10-15 14:26:23 -07005708void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5709 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005710{
5711 struct mgmt_ev_auth_failed ev;
5712
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005713 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005714 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005715 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005716
Marcel Holtmanne5460992013-10-15 14:26:23 -07005717 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005718}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005719
Marcel Holtmann464996a2013-10-15 14:26:24 -07005720void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005721{
5722 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005723 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005724
5725 if (status) {
5726 u8 mgmt_err = mgmt_status(status);
5727 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005728 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005729 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005730 }
5731
Marcel Holtmann464996a2013-10-15 14:26:24 -07005732 if (test_bit(HCI_AUTH, &hdev->flags))
5733 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5734 &hdev->dev_flags);
5735 else
5736 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5737 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005738
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005739 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005740 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005741
Johan Hedberg47990ea2012-02-22 11:58:37 +02005742 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005743 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005744
5745 if (match.sk)
5746 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005747}
5748
Johan Hedberg890ea892013-03-15 17:06:52 -05005749static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005750{
Johan Hedberg890ea892013-03-15 17:06:52 -05005751 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005752 struct hci_cp_write_eir cp;
5753
Johan Hedberg976eb202012-10-24 21:12:01 +03005754 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005755 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005756
Johan Hedbergc80da272012-02-22 15:38:48 +02005757 memset(hdev->eir, 0, sizeof(hdev->eir));
5758
Johan Hedbergcacaf522012-02-21 00:52:42 +02005759 memset(&cp, 0, sizeof(cp));
5760
Johan Hedberg890ea892013-03-15 17:06:52 -05005761 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005762}
5763
Marcel Holtmann3e248562013-10-15 14:26:25 -07005764void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005765{
5766 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005767 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005768 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005769
5770 if (status) {
5771 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005772
5773 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005774 &hdev->dev_flags)) {
5775 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005776 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005777 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005778
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005779 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5780 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005781 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005782 }
5783
5784 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005785 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005786 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005787 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5788 if (!changed)
5789 changed = test_and_clear_bit(HCI_HS_ENABLED,
5790 &hdev->dev_flags);
5791 else
5792 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005793 }
5794
5795 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5796
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005797 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005798 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005799
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005800 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005801 sock_put(match.sk);
5802
Johan Hedberg890ea892013-03-15 17:06:52 -05005803 hci_req_init(&req, hdev);
5804
Johan Hedberg37699722014-06-24 14:00:27 +03005805 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
5806 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
5807 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
5808 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05005809 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03005810 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05005811 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03005812 }
Johan Hedberg890ea892013-03-15 17:06:52 -05005813
5814 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005815}
5816
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005817void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5818{
5819 struct cmd_lookup match = { NULL, hdev };
5820 bool changed = false;
5821
5822 if (status) {
5823 u8 mgmt_err = mgmt_status(status);
5824
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005825 if (enable) {
5826 if (test_and_clear_bit(HCI_SC_ENABLED,
5827 &hdev->dev_flags))
5828 new_settings(hdev, NULL);
5829 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5830 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005831
5832 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5833 cmd_status_rsp, &mgmt_err);
5834 return;
5835 }
5836
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005837 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005838 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005839 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005840 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005841 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5842 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005843
5844 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5845 settings_rsp, &match);
5846
5847 if (changed)
5848 new_settings(hdev, match.sk);
5849
5850 if (match.sk)
5851 sock_put(match.sk);
5852}
5853
Johan Hedberg92da6092013-03-15 17:06:55 -05005854static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005855{
5856 struct cmd_lookup *match = data;
5857
Johan Hedberg90e70452012-02-23 23:09:40 +02005858 if (match->sk == NULL) {
5859 match->sk = cmd->sk;
5860 sock_hold(match->sk);
5861 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005862}
5863
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005864void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5865 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005866{
Johan Hedberg90e70452012-02-23 23:09:40 +02005867 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005868
Johan Hedberg92da6092013-03-15 17:06:55 -05005869 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5870 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5871 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005872
5873 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005874 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5875 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005876
5877 if (match.sk)
5878 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005879}
5880
Marcel Holtmann7667da32013-10-15 14:26:27 -07005881void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005882{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005883 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005884 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005885
Johan Hedberg13928972013-03-15 17:07:00 -05005886 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005887 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005888
5889 memset(&ev, 0, sizeof(ev));
5890 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005891 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005892
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005893 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005894 if (!cmd) {
5895 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005896
Johan Hedberg13928972013-03-15 17:07:00 -05005897 /* If this is a HCI command related to powering on the
5898 * HCI dev don't send any mgmt signals.
5899 */
5900 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005901 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005902 }
5903
Marcel Holtmann7667da32013-10-15 14:26:27 -07005904 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5905 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005906}
Szymon Jancc35938b2011-03-22 13:12:21 +01005907
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005908void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5909 u8 *randomizer192, u8 *hash256,
5910 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005911{
5912 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005913
Johan Hedberg744cf192011-11-08 20:40:14 +02005914 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005915
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005916 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005917 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005918 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005919
5920 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005921 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5922 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005923 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005924 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5925 hash256 && randomizer256) {
5926 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005927
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005928 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5929 memcpy(rp.randomizer192, randomizer192,
5930 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005931
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005932 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5933 memcpy(rp.randomizer256, randomizer256,
5934 sizeof(rp.randomizer256));
5935
5936 cmd_complete(cmd->sk, hdev->id,
5937 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5938 &rp, sizeof(rp));
5939 } else {
5940 struct mgmt_rp_read_local_oob_data rp;
5941
5942 memcpy(rp.hash, hash192, sizeof(rp.hash));
5943 memcpy(rp.randomizer, randomizer192,
5944 sizeof(rp.randomizer));
5945
5946 cmd_complete(cmd->sk, hdev->id,
5947 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5948 &rp, sizeof(rp));
5949 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005950 }
5951
5952 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005953}
Johan Hedberge17acd42011-03-30 23:57:16 +03005954
Marcel Holtmann901801b2013-10-06 23:55:51 -07005955void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02005956 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
5957 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005958 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005959{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005960 char buf[512];
5961 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005962 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005963 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005964
Andre Guedes12602d02013-04-30 15:29:40 -03005965 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005966 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005967
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005968 /* Make sure that the buffer is big enough. The 5 extra bytes
5969 * are for the potential CoD field.
5970 */
5971 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005972 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005973
Johan Hedberg1dc06092012-01-15 21:01:23 +02005974 memset(buf, 0, sizeof(buf));
5975
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005976 irk = hci_get_irk(hdev, bdaddr, addr_type);
5977 if (irk) {
5978 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5979 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5980 } else {
5981 bacpy(&ev->addr.bdaddr, bdaddr);
5982 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5983 }
5984
Johan Hedberge319d2e2012-01-15 19:51:59 +02005985 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005986 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005987 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005988 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005989 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005990
Johan Hedberg1dc06092012-01-15 21:01:23 +02005991 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005992 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005993
Johan Hedberg1dc06092012-01-15 21:01:23 +02005994 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5995 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005996 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005997
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005998 if (scan_rsp_len > 0)
5999 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6000
6001 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6002 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006003
Marcel Holtmann901801b2013-10-06 23:55:51 -07006004 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006005}
Johan Hedberga88a9652011-03-30 13:18:12 +03006006
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006007void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6008 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006009{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006010 struct mgmt_ev_device_found *ev;
6011 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6012 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006013
Johan Hedbergb644ba32012-01-17 21:48:47 +02006014 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006015
Johan Hedbergb644ba32012-01-17 21:48:47 +02006016 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006017
Johan Hedbergb644ba32012-01-17 21:48:47 +02006018 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006019 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006020 ev->rssi = rssi;
6021
6022 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006023 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006024
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006025 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006026
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006027 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006028}
Johan Hedberg314b2382011-04-27 10:29:57 -04006029
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006030void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006031{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006032 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006033 struct pending_cmd *cmd;
6034
Andre Guedes343fb142011-11-22 17:14:19 -03006035 BT_DBG("%s discovering %u", hdev->name, discovering);
6036
Johan Hedberg164a6e72011-11-01 17:06:44 +02006037 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006038 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006039 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006040 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006041
6042 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006043 u8 type = hdev->discovery.type;
6044
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006045 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6046 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006047 mgmt_pending_remove(cmd);
6048 }
6049
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006050 memset(&ev, 0, sizeof(ev));
6051 ev.type = hdev->discovery.type;
6052 ev.discovering = discovering;
6053
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006054 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006055}
Antti Julku5e762442011-08-25 16:48:02 +03006056
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006057int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006058{
6059 struct pending_cmd *cmd;
6060 struct mgmt_ev_device_blocked ev;
6061
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006062 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006063
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006064 bacpy(&ev.addr.bdaddr, bdaddr);
6065 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006066
Johan Hedberg744cf192011-11-08 20:40:14 +02006067 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006068 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006069}
6070
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006071int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006072{
6073 struct pending_cmd *cmd;
6074 struct mgmt_ev_device_unblocked ev;
6075
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006076 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006077
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006078 bacpy(&ev.addr.bdaddr, bdaddr);
6079 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006080
Johan Hedberg744cf192011-11-08 20:40:14 +02006081 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006082 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006083}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006084
6085static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6086{
6087 BT_DBG("%s status %u", hdev->name, status);
6088
6089 /* Clear the advertising mgmt setting if we failed to re-enable it */
6090 if (status) {
6091 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006092 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006093 }
6094}
6095
6096void mgmt_reenable_advertising(struct hci_dev *hdev)
6097{
6098 struct hci_request req;
6099
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006100 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006101 return;
6102
6103 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6104 return;
6105
6106 hci_req_init(&req, hdev);
6107 enable_advertising(&req);
6108
6109 /* If this fails we have no option but to let user space know
6110 * that we've disabled advertising.
6111 */
6112 if (hci_req_run(&req, adv_enable_complete) < 0) {
6113 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006114 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006115 }
6116}