blob: 0fce54412ffdc077f6d337eadc4cfbe20b51ed26 [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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200211
Andre Guedes790eff42012-06-07 19:05:46 -0300212 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200228 kfree_skb(skb);
229
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300230 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200231}
232
Johan Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Holtmann5afeac12014-01-10 02:07:27 -0800389 if (lmp_sc_capable(hdev) ||
390 test_bit(HCI_FORCE_SC, &hdev->dev_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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800443 if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags))
444 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 Hedbergaee9b212012-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
1050static int clean_up_hci_state(struct hci_dev *hdev)
1051{
1052 struct hci_request req;
1053 struct hci_conn *conn;
1054
1055 hci_req_init(&req, hdev);
1056
1057 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1058 test_bit(HCI_PSCAN, &hdev->flags)) {
1059 u8 scan = 0x00;
1060 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1061 }
1062
1063 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1064 disable_advertising(&req);
1065
1066 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Andre Guedesb1efcc22014-02-26 20:21:40 -03001067 hci_req_add_le_scan_disable(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001068 }
1069
1070 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1071 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001072 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001073
Johan Hedbergc9910d02014-02-27 14:35:12 +02001074 switch (conn->state) {
1075 case BT_CONNECTED:
1076 case BT_CONFIG:
1077 dc.handle = cpu_to_le16(conn->handle);
1078 dc.reason = 0x15; /* Terminated due to Power Off */
1079 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1080 break;
1081 case BT_CONNECT:
1082 if (conn->type == LE_LINK)
1083 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1084 0, NULL);
1085 else if (conn->type == ACL_LINK)
1086 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1087 6, &conn->dst);
1088 break;
1089 case BT_CONNECT2:
1090 bacpy(&rej.bdaddr, &conn->dst);
1091 rej.reason = 0x15; /* Terminated due to Power Off */
1092 if (conn->type == ACL_LINK)
1093 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1094 sizeof(rej), &rej);
1095 else if (conn->type == SCO_LINK)
1096 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1097 sizeof(rej), &rej);
1098 break;
1099 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001100 }
1101
1102 return hci_req_run(&req, clean_up_hci_complete);
1103}
1104
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001105static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001106 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001107{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001108 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001109 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001110 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001111
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001112 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001113
Johan Hedberga7e80f22013-01-09 16:05:19 +02001114 if (cp->val != 0x00 && cp->val != 0x01)
1115 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1116 MGMT_STATUS_INVALID_PARAMS);
1117
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001118 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001119
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001120 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1121 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1122 MGMT_STATUS_BUSY);
1123 goto failed;
1124 }
1125
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001126 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1127 cancel_delayed_work(&hdev->power_off);
1128
1129 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001130 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1131 data, len);
1132 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001133 goto failed;
1134 }
1135 }
1136
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001137 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001138 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001139 goto failed;
1140 }
1141
Johan Hedberg03811012010-12-08 00:21:06 +02001142 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1143 if (!cmd) {
1144 err = -ENOMEM;
1145 goto failed;
1146 }
1147
Johan Hedberg8b064a32014-02-24 14:52:22 +02001148 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001149 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001150 err = 0;
1151 } else {
1152 /* Disconnect connections, stop scans, etc */
1153 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001154 if (!err)
1155 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1156 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001157
Johan Hedberg8b064a32014-02-24 14:52:22 +02001158 /* ENODATA means there were no HCI commands queued */
1159 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001160 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001161 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1162 err = 0;
1163 }
1164 }
Johan Hedberg03811012010-12-08 00:21:06 +02001165
1166failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001167 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001168 return err;
1169}
1170
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001171static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1172 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001173{
1174 struct sk_buff *skb;
1175 struct mgmt_hdr *hdr;
1176
Andre Guedes790eff42012-06-07 19:05:46 -03001177 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001178 if (!skb)
1179 return -ENOMEM;
1180
1181 hdr = (void *) skb_put(skb, sizeof(*hdr));
1182 hdr->opcode = cpu_to_le16(event);
1183 if (hdev)
1184 hdr->index = cpu_to_le16(hdev->id);
1185 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001186 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001187 hdr->len = cpu_to_le16(data_len);
1188
1189 if (data)
1190 memcpy(skb_put(skb, data_len), data, data_len);
1191
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001192 /* Time stamp */
1193 __net_timestamp(skb);
1194
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001195 hci_send_to_control(skb, skip_sk);
1196 kfree_skb(skb);
1197
1198 return 0;
1199}
1200
1201static int new_settings(struct hci_dev *hdev, struct sock *skip)
1202{
1203 __le32 ev;
1204
1205 ev = cpu_to_le32(get_current_settings(hdev));
1206
1207 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1208}
1209
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001210struct cmd_lookup {
1211 struct sock *sk;
1212 struct hci_dev *hdev;
1213 u8 mgmt_status;
1214};
1215
1216static void settings_rsp(struct pending_cmd *cmd, void *data)
1217{
1218 struct cmd_lookup *match = data;
1219
1220 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1221
1222 list_del(&cmd->list);
1223
1224 if (match->sk == NULL) {
1225 match->sk = cmd->sk;
1226 sock_hold(match->sk);
1227 }
1228
1229 mgmt_pending_free(cmd);
1230}
1231
1232static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1233{
1234 u8 *status = data;
1235
1236 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1237 mgmt_pending_remove(cmd);
1238}
1239
Johan Hedberge6fe7982013-10-02 15:45:22 +03001240static u8 mgmt_bredr_support(struct hci_dev *hdev)
1241{
1242 if (!lmp_bredr_capable(hdev))
1243 return MGMT_STATUS_NOT_SUPPORTED;
1244 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1245 return MGMT_STATUS_REJECTED;
1246 else
1247 return MGMT_STATUS_SUCCESS;
1248}
1249
1250static u8 mgmt_le_support(struct hci_dev *hdev)
1251{
1252 if (!lmp_le_capable(hdev))
1253 return MGMT_STATUS_NOT_SUPPORTED;
1254 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1255 return MGMT_STATUS_REJECTED;
1256 else
1257 return MGMT_STATUS_SUCCESS;
1258}
1259
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001260static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1261{
1262 struct pending_cmd *cmd;
1263 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001264 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001265 bool changed;
1266
1267 BT_DBG("status 0x%02x", status);
1268
1269 hci_dev_lock(hdev);
1270
1271 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1272 if (!cmd)
1273 goto unlock;
1274
1275 if (status) {
1276 u8 mgmt_err = mgmt_status(status);
1277 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001278 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001279 goto remove_cmd;
1280 }
1281
1282 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001283 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001284 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1285 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001286
1287 if (hdev->discov_timeout > 0) {
1288 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1289 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1290 to);
1291 }
1292 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001293 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1294 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001295 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001296
1297 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1298
1299 if (changed)
1300 new_settings(hdev, cmd->sk);
1301
Marcel Holtmann970ba522013-10-15 06:33:57 -07001302 /* When the discoverable mode gets changed, make sure
1303 * that class of device has the limited discoverable
1304 * bit correctly set.
1305 */
1306 hci_req_init(&req, hdev);
1307 update_class(&req);
1308 hci_req_run(&req, NULL);
1309
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001310remove_cmd:
1311 mgmt_pending_remove(cmd);
1312
1313unlock:
1314 hci_dev_unlock(hdev);
1315}
1316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001317static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001318 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001319{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001320 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001321 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001322 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001323 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001324 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001325 int err;
1326
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001327 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001328
Johan Hedberg9a43e252013-10-20 19:00:07 +03001329 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1330 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001331 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001332 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001333
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001334 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001335 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1336 MGMT_STATUS_INVALID_PARAMS);
1337
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001338 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001339
1340 /* Disabling discoverable requires that no timeout is set,
1341 * and enabling limited discoverable requires a timeout.
1342 */
1343 if ((cp->val == 0x00 && timeout > 0) ||
1344 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001345 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001346 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001347
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001348 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001349
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001350 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001351 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001352 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001353 goto failed;
1354 }
1355
1356 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001357 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001358 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001359 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001360 goto failed;
1361 }
1362
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001363 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001364 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001365 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001366 goto failed;
1367 }
1368
1369 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001370 bool changed = false;
1371
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001372 /* Setting limited discoverable when powered off is
1373 * not a valid operation since it requires a timeout
1374 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1375 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001376 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1377 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1378 changed = true;
1379 }
1380
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001381 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001382 if (err < 0)
1383 goto failed;
1384
1385 if (changed)
1386 err = new_settings(hdev, sk);
1387
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001388 goto failed;
1389 }
1390
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001391 /* If the current mode is the same, then just update the timeout
1392 * value with the new value. And if only the timeout gets updated,
1393 * then no need for any HCI transactions.
1394 */
1395 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1396 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1397 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001398 cancel_delayed_work(&hdev->discov_off);
1399 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001400
Marcel Holtmann36261542013-10-15 08:28:51 -07001401 if (cp->val && hdev->discov_timeout > 0) {
1402 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001403 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001404 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001405 }
1406
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001407 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001408 goto failed;
1409 }
1410
1411 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1412 if (!cmd) {
1413 err = -ENOMEM;
1414 goto failed;
1415 }
1416
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001417 /* Cancel any potential discoverable timeout that might be
1418 * still active and store new timeout value. The arming of
1419 * the timeout happens in the complete handler.
1420 */
1421 cancel_delayed_work(&hdev->discov_off);
1422 hdev->discov_timeout = timeout;
1423
Johan Hedbergb456f872013-10-19 23:38:22 +03001424 /* Limited discoverable mode */
1425 if (cp->val == 0x02)
1426 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1427 else
1428 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1429
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001430 hci_req_init(&req, hdev);
1431
Johan Hedberg9a43e252013-10-20 19:00:07 +03001432 /* The procedure for LE-only controllers is much simpler - just
1433 * update the advertising data.
1434 */
1435 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1436 goto update_ad;
1437
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001438 scan = SCAN_PAGE;
1439
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001440 if (cp->val) {
1441 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001442
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001443 if (cp->val == 0x02) {
1444 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001445 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001446 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1447 hci_cp.iac_lap[1] = 0x8b;
1448 hci_cp.iac_lap[2] = 0x9e;
1449 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1450 hci_cp.iac_lap[4] = 0x8b;
1451 hci_cp.iac_lap[5] = 0x9e;
1452 } else {
1453 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001454 hci_cp.num_iac = 1;
1455 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1456 hci_cp.iac_lap[1] = 0x8b;
1457 hci_cp.iac_lap[2] = 0x9e;
1458 }
1459
1460 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1461 (hci_cp.num_iac * 3) + 1, &hci_cp);
1462
1463 scan |= SCAN_INQUIRY;
1464 } else {
1465 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1466 }
1467
1468 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001469
Johan Hedberg9a43e252013-10-20 19:00:07 +03001470update_ad:
1471 update_adv_data(&req);
1472
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001473 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001474 if (err < 0)
1475 mgmt_pending_remove(cmd);
1476
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001477failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001478 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001479 return err;
1480}
1481
Johan Hedberg406d7802013-03-15 17:07:09 -05001482static void write_fast_connectable(struct hci_request *req, bool enable)
1483{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001484 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001485 struct hci_cp_write_page_scan_activity acp;
1486 u8 type;
1487
Johan Hedberg547003b2013-10-21 16:51:53 +03001488 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1489 return;
1490
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001491 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1492 return;
1493
Johan Hedberg406d7802013-03-15 17:07:09 -05001494 if (enable) {
1495 type = PAGE_SCAN_TYPE_INTERLACED;
1496
1497 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001498 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001499 } else {
1500 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1501
1502 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001503 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001504 }
1505
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001506 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001507
Johan Hedbergbd98b992013-03-15 17:07:13 -05001508 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1509 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1510 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1511 sizeof(acp), &acp);
1512
1513 if (hdev->page_scan_type != type)
1514 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001515}
1516
Johan Hedberg2b76f452013-03-15 17:07:04 -05001517static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1518{
1519 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001520 struct mgmt_mode *cp;
1521 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001522
1523 BT_DBG("status 0x%02x", status);
1524
1525 hci_dev_lock(hdev);
1526
1527 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1528 if (!cmd)
1529 goto unlock;
1530
Johan Hedberg37438c12013-10-14 16:20:05 +03001531 if (status) {
1532 u8 mgmt_err = mgmt_status(status);
1533 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1534 goto remove_cmd;
1535 }
1536
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001537 cp = cmd->param;
1538 if (cp->val)
1539 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1540 else
1541 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1542
Johan Hedberg2b76f452013-03-15 17:07:04 -05001543 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1544
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001545 if (changed)
1546 new_settings(hdev, cmd->sk);
1547
Johan Hedberg37438c12013-10-14 16:20:05 +03001548remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001549 mgmt_pending_remove(cmd);
1550
1551unlock:
1552 hci_dev_unlock(hdev);
1553}
1554
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001555static int set_connectable_update_settings(struct hci_dev *hdev,
1556 struct sock *sk, u8 val)
1557{
1558 bool changed = false;
1559 int err;
1560
1561 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1562 changed = true;
1563
1564 if (val) {
1565 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1566 } else {
1567 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1568 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1569 }
1570
1571 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1572 if (err < 0)
1573 return err;
1574
1575 if (changed)
1576 return new_settings(hdev, sk);
1577
1578 return 0;
1579}
1580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001581static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001582 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001583{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001584 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001585 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001586 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001587 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001588 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001590 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001591
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001592 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1593 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001594 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001595 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001596
Johan Hedberga7e80f22013-01-09 16:05:19 +02001597 if (cp->val != 0x00 && cp->val != 0x01)
1598 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1599 MGMT_STATUS_INVALID_PARAMS);
1600
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001601 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001602
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001603 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001604 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001605 goto failed;
1606 }
1607
1608 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001609 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001610 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001611 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001612 goto failed;
1613 }
1614
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001615 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1616 if (!cmd) {
1617 err = -ENOMEM;
1618 goto failed;
1619 }
1620
Johan Hedberg2b76f452013-03-15 17:07:04 -05001621 hci_req_init(&req, hdev);
1622
Johan Hedberg9a43e252013-10-20 19:00:07 +03001623 /* If BR/EDR is not enabled and we disable advertising as a
1624 * by-product of disabling connectable, we need to update the
1625 * advertising flags.
1626 */
1627 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1628 if (!cp->val) {
1629 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1630 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1631 }
1632 update_adv_data(&req);
1633 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001634 if (cp->val) {
1635 scan = SCAN_PAGE;
1636 } else {
1637 scan = 0;
1638
1639 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001640 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001641 cancel_delayed_work(&hdev->discov_off);
1642 }
1643
1644 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1645 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001646
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001647 /* If we're going from non-connectable to connectable or
1648 * vice-versa when fast connectable is enabled ensure that fast
1649 * connectable gets disabled. write_fast_connectable won't do
1650 * anything if the page scan parameters are already what they
1651 * should be.
1652 */
1653 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001654 write_fast_connectable(&req, false);
1655
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001656 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1657 hci_conn_num(hdev, LE_LINK) == 0) {
1658 disable_advertising(&req);
1659 enable_advertising(&req);
1660 }
1661
Johan Hedberg2b76f452013-03-15 17:07:04 -05001662 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001663 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001664 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001665 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001666 err = set_connectable_update_settings(hdev, sk,
1667 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001668 goto failed;
1669 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001670
1671failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001672 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001673 return err;
1674}
1675
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001676static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001677 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001678{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001679 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001680 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001681 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001682
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001683 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001684
Johan Hedberga7e80f22013-01-09 16:05:19 +02001685 if (cp->val != 0x00 && cp->val != 0x01)
1686 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1687 MGMT_STATUS_INVALID_PARAMS);
1688
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001689 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001690
1691 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001692 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001693 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001694 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001695
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001696 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001697 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001698 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001699
Marcel Holtmann55594352013-10-06 16:11:57 -07001700 if (changed)
1701 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001702
Marcel Holtmann55594352013-10-06 16:11:57 -07001703unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001704 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001705 return err;
1706}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001707
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001708static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1709 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001710{
1711 struct mgmt_mode *cp = data;
1712 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001713 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001714 int err;
1715
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001716 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001717
Johan Hedberge6fe7982013-10-02 15:45:22 +03001718 status = mgmt_bredr_support(hdev);
1719 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001720 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001721 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001722
Johan Hedberga7e80f22013-01-09 16:05:19 +02001723 if (cp->val != 0x00 && cp->val != 0x01)
1724 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1725 MGMT_STATUS_INVALID_PARAMS);
1726
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001727 hci_dev_lock(hdev);
1728
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001729 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001730 bool changed = false;
1731
1732 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001733 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001734 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1735 changed = true;
1736 }
1737
1738 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1739 if (err < 0)
1740 goto failed;
1741
1742 if (changed)
1743 err = new_settings(hdev, sk);
1744
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001745 goto failed;
1746 }
1747
1748 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001749 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001750 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001751 goto failed;
1752 }
1753
1754 val = !!cp->val;
1755
1756 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1757 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1758 goto failed;
1759 }
1760
1761 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1762 if (!cmd) {
1763 err = -ENOMEM;
1764 goto failed;
1765 }
1766
1767 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1768 if (err < 0) {
1769 mgmt_pending_remove(cmd);
1770 goto failed;
1771 }
1772
1773failed:
1774 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001775 return err;
1776}
1777
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001778static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001779{
1780 struct mgmt_mode *cp = data;
1781 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001782 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001783 int err;
1784
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001785 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001786
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001787 status = mgmt_bredr_support(hdev);
1788 if (status)
1789 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1790
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001791 if (!lmp_ssp_capable(hdev))
1792 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1793 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001794
Johan Hedberga7e80f22013-01-09 16:05:19 +02001795 if (cp->val != 0x00 && cp->val != 0x01)
1796 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1797 MGMT_STATUS_INVALID_PARAMS);
1798
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001799 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001800
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001801 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001802 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001803
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001804 if (cp->val) {
1805 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1806 &hdev->dev_flags);
1807 } else {
1808 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1809 &hdev->dev_flags);
1810 if (!changed)
1811 changed = test_and_clear_bit(HCI_HS_ENABLED,
1812 &hdev->dev_flags);
1813 else
1814 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001815 }
1816
1817 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1818 if (err < 0)
1819 goto failed;
1820
1821 if (changed)
1822 err = new_settings(hdev, sk);
1823
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001824 goto failed;
1825 }
1826
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001827 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1828 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001829 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1830 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001831 goto failed;
1832 }
1833
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001834 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001835 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1836 goto failed;
1837 }
1838
1839 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1840 if (!cmd) {
1841 err = -ENOMEM;
1842 goto failed;
1843 }
1844
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001845 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001846 if (err < 0) {
1847 mgmt_pending_remove(cmd);
1848 goto failed;
1849 }
1850
1851failed:
1852 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001853 return err;
1854}
1855
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001856static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001857{
1858 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001859 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001860 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001861 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001862
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001863 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001864
Johan Hedberge6fe7982013-10-02 15:45:22 +03001865 status = mgmt_bredr_support(hdev);
1866 if (status)
1867 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001868
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001869 if (!lmp_ssp_capable(hdev))
1870 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1871 MGMT_STATUS_NOT_SUPPORTED);
1872
1873 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1874 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1875 MGMT_STATUS_REJECTED);
1876
Johan Hedberga7e80f22013-01-09 16:05:19 +02001877 if (cp->val != 0x00 && cp->val != 0x01)
1878 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1879 MGMT_STATUS_INVALID_PARAMS);
1880
Marcel Holtmannee392692013-10-01 22:59:23 -07001881 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001882
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001883 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001884 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001885 } else {
1886 if (hdev_is_powered(hdev)) {
1887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1888 MGMT_STATUS_REJECTED);
1889 goto unlock;
1890 }
1891
Marcel Holtmannee392692013-10-01 22:59:23 -07001892 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001893 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001894
1895 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1896 if (err < 0)
1897 goto unlock;
1898
1899 if (changed)
1900 err = new_settings(hdev, sk);
1901
1902unlock:
1903 hci_dev_unlock(hdev);
1904 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001905}
1906
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001907static void le_enable_complete(struct hci_dev *hdev, u8 status)
1908{
1909 struct cmd_lookup match = { NULL, hdev };
1910
1911 if (status) {
1912 u8 mgmt_err = mgmt_status(status);
1913
1914 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1915 &mgmt_err);
1916 return;
1917 }
1918
1919 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1920
1921 new_settings(hdev, match.sk);
1922
1923 if (match.sk)
1924 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001925
1926 /* Make sure the controller has a good default for
1927 * advertising data. Restrict the update to when LE
1928 * has actually been enabled. During power on, the
1929 * update in powered_update_hci will take care of it.
1930 */
1931 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1932 struct hci_request req;
1933
1934 hci_dev_lock(hdev);
1935
1936 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001937 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001938 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001939 hci_req_run(&req, NULL);
1940
1941 hci_dev_unlock(hdev);
1942 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001943}
1944
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001945static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001946{
1947 struct mgmt_mode *cp = data;
1948 struct hci_cp_write_le_host_supported hci_cp;
1949 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001950 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001951 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001952 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001953
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001954 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001955
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001956 if (!lmp_le_capable(hdev))
1957 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1958 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001959
Johan Hedberga7e80f22013-01-09 16:05:19 +02001960 if (cp->val != 0x00 && cp->val != 0x01)
1961 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1962 MGMT_STATUS_INVALID_PARAMS);
1963
Johan Hedbergc73eee92013-04-19 18:35:21 +03001964 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03001965 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03001966 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1967 MGMT_STATUS_REJECTED);
1968
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001969 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001970
1971 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001972 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001973
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001974 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02001975 bool changed = false;
1976
1977 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1978 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1979 changed = true;
1980 }
1981
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02001982 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
1983 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03001984 changed = true;
1985 }
1986
Johan Hedberg06199cf2012-02-22 16:37:11 +02001987 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1988 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08001989 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001990
1991 if (changed)
1992 err = new_settings(hdev, sk);
1993
Johan Hedberg1de028c2012-02-29 19:55:35 -08001994 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001995 }
1996
Johan Hedberg4375f102013-09-25 13:26:10 +03001997 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
1998 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001999 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002000 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002001 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002002 }
2003
2004 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2005 if (!cmd) {
2006 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002007 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002008 }
2009
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002010 hci_req_init(&req, hdev);
2011
Johan Hedberg06199cf2012-02-22 16:37:11 +02002012 memset(&hci_cp, 0, sizeof(hci_cp));
2013
2014 if (val) {
2015 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002016 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002017 } else {
2018 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2019 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002020 }
2021
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002022 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2023 &hci_cp);
2024
2025 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302026 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002027 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002028
Johan Hedberg1de028c2012-02-29 19:55:35 -08002029unlock:
2030 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002031 return err;
2032}
2033
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002034/* This is a helper function to test for pending mgmt commands that can
2035 * cause CoD or EIR HCI commands. We can only allow one such pending
2036 * mgmt command at a time since otherwise we cannot easily track what
2037 * the current values are, will be, and based on that calculate if a new
2038 * HCI command needs to be sent and if yes with what value.
2039 */
2040static bool pending_eir_or_class(struct hci_dev *hdev)
2041{
2042 struct pending_cmd *cmd;
2043
2044 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2045 switch (cmd->opcode) {
2046 case MGMT_OP_ADD_UUID:
2047 case MGMT_OP_REMOVE_UUID:
2048 case MGMT_OP_SET_DEV_CLASS:
2049 case MGMT_OP_SET_POWERED:
2050 return true;
2051 }
2052 }
2053
2054 return false;
2055}
2056
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002057static const u8 bluetooth_base_uuid[] = {
2058 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2059 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2060};
2061
2062static u8 get_uuid_size(const u8 *uuid)
2063{
2064 u32 val;
2065
2066 if (memcmp(uuid, bluetooth_base_uuid, 12))
2067 return 128;
2068
2069 val = get_unaligned_le32(&uuid[12]);
2070 if (val > 0xffff)
2071 return 32;
2072
2073 return 16;
2074}
2075
Johan Hedberg92da6092013-03-15 17:06:55 -05002076static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2077{
2078 struct pending_cmd *cmd;
2079
2080 hci_dev_lock(hdev);
2081
2082 cmd = mgmt_pending_find(mgmt_op, hdev);
2083 if (!cmd)
2084 goto unlock;
2085
2086 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2087 hdev->dev_class, 3);
2088
2089 mgmt_pending_remove(cmd);
2090
2091unlock:
2092 hci_dev_unlock(hdev);
2093}
2094
2095static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2096{
2097 BT_DBG("status 0x%02x", status);
2098
2099 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2100}
2101
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002102static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002103{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002104 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002105 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002106 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002107 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002108 int err;
2109
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002110 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002111
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002112 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002113
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002114 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002115 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002116 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002117 goto failed;
2118 }
2119
Andre Guedes92c4c202012-06-07 19:05:44 -03002120 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002121 if (!uuid) {
2122 err = -ENOMEM;
2123 goto failed;
2124 }
2125
2126 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002127 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002128 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002129
Johan Hedbergde66aa62013-01-27 00:31:27 +02002130 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002131
Johan Hedberg890ea892013-03-15 17:06:52 -05002132 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002133
Johan Hedberg890ea892013-03-15 17:06:52 -05002134 update_class(&req);
2135 update_eir(&req);
2136
Johan Hedberg92da6092013-03-15 17:06:55 -05002137 err = hci_req_run(&req, add_uuid_complete);
2138 if (err < 0) {
2139 if (err != -ENODATA)
2140 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002141
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002142 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002143 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002144 goto failed;
2145 }
2146
2147 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002148 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002149 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002150 goto failed;
2151 }
2152
2153 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002154
2155failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002156 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002157 return err;
2158}
2159
Johan Hedberg24b78d02012-02-23 23:24:30 +02002160static bool enable_service_cache(struct hci_dev *hdev)
2161{
2162 if (!hdev_is_powered(hdev))
2163 return false;
2164
2165 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002166 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2167 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002168 return true;
2169 }
2170
2171 return false;
2172}
2173
Johan Hedberg92da6092013-03-15 17:06:55 -05002174static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2175{
2176 BT_DBG("status 0x%02x", status);
2177
2178 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2179}
2180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002181static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002182 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002183{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002184 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002185 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002186 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002187 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 -05002188 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002189 int err, found;
2190
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002191 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002192
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002193 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002194
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002195 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002196 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002197 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002198 goto unlock;
2199 }
2200
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002201 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002202 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002203
Johan Hedberg24b78d02012-02-23 23:24:30 +02002204 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002205 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002206 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002207 goto unlock;
2208 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002209
Johan Hedberg9246a862012-02-23 21:33:16 +02002210 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002211 }
2212
2213 found = 0;
2214
Johan Hedberg056341c2013-01-27 00:31:30 +02002215 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002216 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2217 continue;
2218
2219 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002220 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002221 found++;
2222 }
2223
2224 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002225 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002226 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002227 goto unlock;
2228 }
2229
Johan Hedberg9246a862012-02-23 21:33:16 +02002230update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002231 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002232
Johan Hedberg890ea892013-03-15 17:06:52 -05002233 update_class(&req);
2234 update_eir(&req);
2235
Johan Hedberg92da6092013-03-15 17:06:55 -05002236 err = hci_req_run(&req, remove_uuid_complete);
2237 if (err < 0) {
2238 if (err != -ENODATA)
2239 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002240
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002241 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002242 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002243 goto unlock;
2244 }
2245
2246 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002247 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002248 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002249 goto unlock;
2250 }
2251
2252 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002253
2254unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002255 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002256 return err;
2257}
2258
Johan Hedberg92da6092013-03-15 17:06:55 -05002259static void set_class_complete(struct hci_dev *hdev, u8 status)
2260{
2261 BT_DBG("status 0x%02x", status);
2262
2263 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2264}
2265
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002266static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002267 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002268{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002269 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002270 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002271 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002272 int err;
2273
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002274 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002275
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002276 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002277 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2278 MGMT_STATUS_NOT_SUPPORTED);
2279
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002280 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002281
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002282 if (pending_eir_or_class(hdev)) {
2283 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2284 MGMT_STATUS_BUSY);
2285 goto unlock;
2286 }
2287
2288 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2289 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2290 MGMT_STATUS_INVALID_PARAMS);
2291 goto unlock;
2292 }
2293
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002294 hdev->major_class = cp->major;
2295 hdev->minor_class = cp->minor;
2296
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002297 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002298 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002299 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002300 goto unlock;
2301 }
2302
Johan Hedberg890ea892013-03-15 17:06:52 -05002303 hci_req_init(&req, hdev);
2304
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002305 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002306 hci_dev_unlock(hdev);
2307 cancel_delayed_work_sync(&hdev->service_cache);
2308 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002309 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002310 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002311
Johan Hedberg890ea892013-03-15 17:06:52 -05002312 update_class(&req);
2313
Johan Hedberg92da6092013-03-15 17:06:55 -05002314 err = hci_req_run(&req, set_class_complete);
2315 if (err < 0) {
2316 if (err != -ENODATA)
2317 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002318
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002319 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002320 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002321 goto unlock;
2322 }
2323
2324 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002325 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002326 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002327 goto unlock;
2328 }
2329
2330 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002331
Johan Hedbergb5235a62012-02-21 14:32:24 +02002332unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002333 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002334 return err;
2335}
2336
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002337static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002338 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002339{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002340 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002341 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002342 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002343 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002344
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002345 BT_DBG("request for %s", hdev->name);
2346
2347 if (!lmp_bredr_capable(hdev))
2348 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2349 MGMT_STATUS_NOT_SUPPORTED);
2350
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002351 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002352
Johan Hedberg86742e12011-11-07 23:13:38 +02002353 expected_len = sizeof(*cp) + key_count *
2354 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002355 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002356 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002357 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002358 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002359 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002360 }
2361
Johan Hedberg4ae14302013-01-20 14:27:13 +02002362 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2363 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2364 MGMT_STATUS_INVALID_PARAMS);
2365
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002366 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002367 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002368
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002369 for (i = 0; i < key_count; i++) {
2370 struct mgmt_link_key_info *key = &cp->keys[i];
2371
Marcel Holtmann8e991132014-01-10 02:07:25 -08002372 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002373 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2374 MGMT_STATUS_INVALID_PARAMS);
2375 }
2376
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002377 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002378
2379 hci_link_keys_clear(hdev);
2380
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002381 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002382 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002383 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002384 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2385
2386 if (changed)
2387 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002388
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002389 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002390 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002391
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002392 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002393 key->type, key->pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002394 }
2395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002397
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002398 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002399
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002400 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002401}
2402
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002403static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002404 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002405{
2406 struct mgmt_ev_device_unpaired ev;
2407
2408 bacpy(&ev.addr.bdaddr, bdaddr);
2409 ev.addr.type = addr_type;
2410
2411 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002412 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002413}
2414
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002415static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002416 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002417{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002418 struct mgmt_cp_unpair_device *cp = data;
2419 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002420 struct hci_cp_disconnect dc;
2421 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002422 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002423 int err;
2424
Johan Hedberga8a1d192011-11-10 15:54:38 +02002425 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002426 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2427 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002428
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002429 if (!bdaddr_type_is_valid(cp->addr.type))
2430 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2431 MGMT_STATUS_INVALID_PARAMS,
2432 &rp, sizeof(rp));
2433
Johan Hedberg118da702013-01-20 14:27:20 +02002434 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2435 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2436 MGMT_STATUS_INVALID_PARAMS,
2437 &rp, sizeof(rp));
2438
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002439 hci_dev_lock(hdev);
2440
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002441 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002442 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002443 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002444 goto unlock;
2445 }
2446
Johan Hedberge0b2b272014-02-18 17:14:31 +02002447 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002448 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002449 } else {
2450 u8 addr_type;
2451
2452 if (cp->addr.type == BDADDR_LE_PUBLIC)
2453 addr_type = ADDR_LE_DEV_PUBLIC;
2454 else
2455 addr_type = ADDR_LE_DEV_RANDOM;
2456
Johan Hedberga7ec7332014-02-18 17:14:35 +02002457 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2458
Andre Guedesa9b0a042014-02-26 20:21:52 -03002459 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2460
Johan Hedberge0b2b272014-02-18 17:14:31 +02002461 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2462 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002463
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002464 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002465 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002466 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002467 goto unlock;
2468 }
2469
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002470 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002471 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002472 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002473 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002474 else
2475 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002476 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002477 } else {
2478 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002479 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002480
Johan Hedberga8a1d192011-11-10 15:54:38 +02002481 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002482 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002483 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002484 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002485 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002486 }
2487
Johan Hedberg124f6e32012-02-09 13:50:12 +02002488 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002489 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002490 if (!cmd) {
2491 err = -ENOMEM;
2492 goto unlock;
2493 }
2494
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002495 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002496 dc.reason = 0x13; /* Remote User Terminated Connection */
2497 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2498 if (err < 0)
2499 mgmt_pending_remove(cmd);
2500
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002501unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002502 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002503 return err;
2504}
2505
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002506static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002507 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002508{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002509 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002510 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002511 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002512 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002513 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002514 int err;
2515
2516 BT_DBG("");
2517
Johan Hedberg06a63b12013-01-20 14:27:21 +02002518 memset(&rp, 0, sizeof(rp));
2519 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2520 rp.addr.type = cp->addr.type;
2521
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002522 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002523 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2524 MGMT_STATUS_INVALID_PARAMS,
2525 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002526
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002527 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002528
2529 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002530 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2531 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002532 goto failed;
2533 }
2534
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002535 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002536 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2537 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002538 goto failed;
2539 }
2540
Andre Guedes591f47f2012-04-24 21:02:49 -03002541 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002542 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2543 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002544 else
2545 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002546
Vishal Agarwalf9607272012-06-13 05:32:43 +05302547 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002548 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2549 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002550 goto failed;
2551 }
2552
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002553 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002554 if (!cmd) {
2555 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002556 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002557 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002558
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002559 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002560 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002561
2562 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2563 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002564 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002565
2566failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002567 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002568 return err;
2569}
2570
Andre Guedes57c14772012-04-24 21:02:50 -03002571static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002572{
2573 switch (link_type) {
2574 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002575 switch (addr_type) {
2576 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002577 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002578
Johan Hedberg48264f02011-11-09 13:58:58 +02002579 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002580 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002581 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002582 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002583
Johan Hedberg4c659c32011-11-07 23:13:39 +02002584 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002585 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002586 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002587 }
2588}
2589
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002590static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2591 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002592{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002593 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002594 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002595 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002596 int err;
2597 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002598
2599 BT_DBG("");
2600
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002601 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002602
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002603 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002604 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002605 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002606 goto unlock;
2607 }
2608
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002609 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002610 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2611 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002612 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002613 }
2614
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002615 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002616 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002617 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002618 err = -ENOMEM;
2619 goto unlock;
2620 }
2621
Johan Hedberg2784eb42011-01-21 13:56:35 +02002622 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002623 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002624 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2625 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002626 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002627 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002628 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002629 continue;
2630 i++;
2631 }
2632
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002633 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002634
Johan Hedberg4c659c32011-11-07 23:13:39 +02002635 /* Recalculate length in case of filtered SCO connections, etc */
2636 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002637
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002638 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002639 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002640
Johan Hedberga38528f2011-01-22 06:46:43 +02002641 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002642
2643unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002644 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002645 return err;
2646}
2647
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002648static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002649 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002650{
2651 struct pending_cmd *cmd;
2652 int err;
2653
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002654 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002655 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002656 if (!cmd)
2657 return -ENOMEM;
2658
Johan Hedbergd8457692012-02-17 14:24:57 +02002659 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002660 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002661 if (err < 0)
2662 mgmt_pending_remove(cmd);
2663
2664 return err;
2665}
2666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002667static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002668 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002669{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002670 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002671 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002672 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002673 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002674 int err;
2675
2676 BT_DBG("");
2677
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002678 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002679
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002680 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002681 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002682 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002683 goto failed;
2684 }
2685
Johan Hedbergd8457692012-02-17 14:24:57 +02002686 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002687 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002688 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002689 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002690 goto failed;
2691 }
2692
2693 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002694 struct mgmt_cp_pin_code_neg_reply ncp;
2695
2696 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002697
2698 BT_ERR("PIN code is not 16 bytes long");
2699
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002700 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002701 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002702 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002703 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002704
2705 goto failed;
2706 }
2707
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002708 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002709 if (!cmd) {
2710 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002711 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002712 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002713
Johan Hedbergd8457692012-02-17 14:24:57 +02002714 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002715 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002716 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002717
2718 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2719 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002720 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002721
2722failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002723 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002724 return err;
2725}
2726
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002727static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2728 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002729{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002730 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002731
2732 BT_DBG("");
2733
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002734 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002735
2736 hdev->io_capability = cp->io_capability;
2737
2738 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002739 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002740
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002741 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002742
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002743 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2744 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002745}
2746
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002747static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002748{
2749 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002750 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002751
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002752 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002753 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2754 continue;
2755
Johan Hedberge9a416b2011-02-19 12:05:56 -03002756 if (cmd->user_data != conn)
2757 continue;
2758
2759 return cmd;
2760 }
2761
2762 return NULL;
2763}
2764
2765static void pairing_complete(struct pending_cmd *cmd, u8 status)
2766{
2767 struct mgmt_rp_pair_device rp;
2768 struct hci_conn *conn = cmd->user_data;
2769
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002770 bacpy(&rp.addr.bdaddr, &conn->dst);
2771 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002772
Johan Hedbergaee9b212012-02-18 15:07:59 +02002773 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002774 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002775
2776 /* So we don't get further callbacks for this connection */
2777 conn->connect_cfm_cb = NULL;
2778 conn->security_cfm_cb = NULL;
2779 conn->disconn_cfm_cb = NULL;
2780
David Herrmann76a68ba2013-04-06 20:28:37 +02002781 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002782
Johan Hedberga664b5b2011-02-19 12:06:02 -03002783 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002784}
2785
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002786void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2787{
2788 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2789 struct pending_cmd *cmd;
2790
2791 cmd = find_pairing(conn);
2792 if (cmd)
2793 pairing_complete(cmd, status);
2794}
2795
Johan Hedberge9a416b2011-02-19 12:05:56 -03002796static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2797{
2798 struct pending_cmd *cmd;
2799
2800 BT_DBG("status %u", status);
2801
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002802 cmd = find_pairing(conn);
2803 if (!cmd)
2804 BT_DBG("Unable to find a pending command");
2805 else
Johan Hedberge2113262012-02-18 15:20:03 +02002806 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002807}
2808
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002809static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302810{
2811 struct pending_cmd *cmd;
2812
2813 BT_DBG("status %u", status);
2814
2815 if (!status)
2816 return;
2817
2818 cmd = find_pairing(conn);
2819 if (!cmd)
2820 BT_DBG("Unable to find a pending command");
2821 else
2822 pairing_complete(cmd, mgmt_status(status));
2823}
2824
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002825static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002826 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002827{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002828 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002829 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002830 struct pending_cmd *cmd;
2831 u8 sec_level, auth_type;
2832 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002833 int err;
2834
2835 BT_DBG("");
2836
Szymon Jancf950a30e2013-01-18 12:48:07 +01002837 memset(&rp, 0, sizeof(rp));
2838 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2839 rp.addr.type = cp->addr.type;
2840
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002841 if (!bdaddr_type_is_valid(cp->addr.type))
2842 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2843 MGMT_STATUS_INVALID_PARAMS,
2844 &rp, sizeof(rp));
2845
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002846 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002847
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002848 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002849 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2850 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002851 goto unlock;
2852 }
2853
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002854 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002855 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002856
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002857 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002858 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2859 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002860 } else {
2861 u8 addr_type;
2862
2863 /* Convert from L2CAP channel address type to HCI address type
2864 */
2865 if (cp->addr.type == BDADDR_LE_PUBLIC)
2866 addr_type = ADDR_LE_DEV_PUBLIC;
2867 else
2868 addr_type = ADDR_LE_DEV_RANDOM;
2869
2870 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002871 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002872 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002873
Ville Tervo30e76272011-02-22 16:10:53 -03002874 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002875 int status;
2876
2877 if (PTR_ERR(conn) == -EBUSY)
2878 status = MGMT_STATUS_BUSY;
2879 else
2880 status = MGMT_STATUS_CONNECT_FAILED;
2881
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002882 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002883 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002884 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002885 goto unlock;
2886 }
2887
2888 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002889 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002890 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002891 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002892 goto unlock;
2893 }
2894
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002895 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002896 if (!cmd) {
2897 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002898 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002899 goto unlock;
2900 }
2901
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002902 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002903 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002904 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002905 conn->security_cfm_cb = pairing_complete_cb;
2906 conn->disconn_cfm_cb = pairing_complete_cb;
2907 } else {
2908 conn->connect_cfm_cb = le_pairing_complete_cb;
2909 conn->security_cfm_cb = le_pairing_complete_cb;
2910 conn->disconn_cfm_cb = le_pairing_complete_cb;
2911 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002912
Johan Hedberge9a416b2011-02-19 12:05:56 -03002913 conn->io_capability = cp->io_cap;
2914 cmd->user_data = conn;
2915
2916 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002917 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002918 pairing_complete(cmd, 0);
2919
2920 err = 0;
2921
2922unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002923 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002924 return err;
2925}
2926
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002927static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2928 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002929{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002930 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002931 struct pending_cmd *cmd;
2932 struct hci_conn *conn;
2933 int err;
2934
2935 BT_DBG("");
2936
Johan Hedberg28424702012-02-02 04:02:29 +02002937 hci_dev_lock(hdev);
2938
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002939 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002940 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002941 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002942 goto unlock;
2943 }
2944
Johan Hedberg28424702012-02-02 04:02:29 +02002945 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2946 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002947 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002948 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002949 goto unlock;
2950 }
2951
2952 conn = cmd->user_data;
2953
2954 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002955 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002956 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002957 goto unlock;
2958 }
2959
2960 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2961
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002962 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002963 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02002964unlock:
2965 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02002966 return err;
2967}
2968
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002969static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05002970 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002971 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03002972{
Johan Hedberga5c29682011-02-19 12:05:57 -03002973 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08002974 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002975 int err;
2976
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002977 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02002978
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002979 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002980 err = cmd_complete(sk, hdev->id, mgmt_op,
2981 MGMT_STATUS_NOT_POWERED, addr,
2982 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08002983 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002984 }
2985
Johan Hedberg1707c602013-03-15 17:07:15 -05002986 if (addr->type == BDADDR_BREDR)
2987 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02002988 else
Johan Hedberg1707c602013-03-15 17:07:15 -05002989 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08002990
Johan Hedberg272d90d2012-02-09 15:26:12 +02002991 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002992 err = cmd_complete(sk, hdev->id, mgmt_op,
2993 MGMT_STATUS_NOT_CONNECTED, addr,
2994 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02002995 goto done;
2996 }
2997
Johan Hedberg1707c602013-03-15 17:07:15 -05002998 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08002999 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08003000 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08003001
Brian Gix5fe57d92011-12-21 16:12:13 -08003002 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003003 err = cmd_complete(sk, hdev->id, mgmt_op,
3004 MGMT_STATUS_SUCCESS, addr,
3005 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003006 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003007 err = cmd_complete(sk, hdev->id, mgmt_op,
3008 MGMT_STATUS_FAILED, addr,
3009 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003010
Brian Gix47c15e22011-11-16 13:53:14 -08003011 goto done;
3012 }
3013
Johan Hedberg1707c602013-03-15 17:07:15 -05003014 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003015 if (!cmd) {
3016 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003017 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003018 }
3019
Brian Gix0df4c182011-11-16 13:53:13 -08003020 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003021 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3022 struct hci_cp_user_passkey_reply cp;
3023
Johan Hedberg1707c602013-03-15 17:07:15 -05003024 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003025 cp.passkey = passkey;
3026 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3027 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003028 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3029 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003030
Johan Hedberga664b5b2011-02-19 12:06:02 -03003031 if (err < 0)
3032 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003033
Brian Gix0df4c182011-11-16 13:53:13 -08003034done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003035 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003036 return err;
3037}
3038
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303039static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3040 void *data, u16 len)
3041{
3042 struct mgmt_cp_pin_code_neg_reply *cp = data;
3043
3044 BT_DBG("");
3045
Johan Hedberg1707c602013-03-15 17:07:15 -05003046 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303047 MGMT_OP_PIN_CODE_NEG_REPLY,
3048 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3049}
3050
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003051static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3052 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003053{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003054 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003055
3056 BT_DBG("");
3057
3058 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003059 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003060 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003061
Johan Hedberg1707c602013-03-15 17:07:15 -05003062 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003063 MGMT_OP_USER_CONFIRM_REPLY,
3064 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003065}
3066
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003067static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003068 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003069{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003070 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003071
3072 BT_DBG("");
3073
Johan Hedberg1707c602013-03-15 17:07:15 -05003074 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003075 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3076 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003077}
3078
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003079static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3080 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003081{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003082 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003083
3084 BT_DBG("");
3085
Johan Hedberg1707c602013-03-15 17:07:15 -05003086 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003087 MGMT_OP_USER_PASSKEY_REPLY,
3088 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003089}
3090
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003091static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003092 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003093{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003094 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003095
3096 BT_DBG("");
3097
Johan Hedberg1707c602013-03-15 17:07:15 -05003098 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003099 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3100 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003101}
3102
Johan Hedberg13928972013-03-15 17:07:00 -05003103static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003104{
Johan Hedberg13928972013-03-15 17:07:00 -05003105 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003106 struct hci_cp_write_local_name cp;
3107
Johan Hedberg13928972013-03-15 17:07:00 -05003108 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003109
Johan Hedberg890ea892013-03-15 17:06:52 -05003110 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003111}
3112
Johan Hedberg13928972013-03-15 17:07:00 -05003113static void set_name_complete(struct hci_dev *hdev, u8 status)
3114{
3115 struct mgmt_cp_set_local_name *cp;
3116 struct pending_cmd *cmd;
3117
3118 BT_DBG("status 0x%02x", status);
3119
3120 hci_dev_lock(hdev);
3121
3122 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3123 if (!cmd)
3124 goto unlock;
3125
3126 cp = cmd->param;
3127
3128 if (status)
3129 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3130 mgmt_status(status));
3131 else
3132 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3133 cp, sizeof(*cp));
3134
3135 mgmt_pending_remove(cmd);
3136
3137unlock:
3138 hci_dev_unlock(hdev);
3139}
3140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003141static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003142 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003143{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003144 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003145 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003146 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003147 int err;
3148
3149 BT_DBG("");
3150
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003151 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003152
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003153 /* If the old values are the same as the new ones just return a
3154 * direct command complete event.
3155 */
3156 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3157 !memcmp(hdev->short_name, cp->short_name,
3158 sizeof(hdev->short_name))) {
3159 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3160 data, len);
3161 goto failed;
3162 }
3163
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003164 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003165
Johan Hedbergb5235a62012-02-21 14:32:24 +02003166 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003167 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003168
3169 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003170 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003171 if (err < 0)
3172 goto failed;
3173
3174 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003175 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003176
Johan Hedbergb5235a62012-02-21 14:32:24 +02003177 goto failed;
3178 }
3179
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003180 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003181 if (!cmd) {
3182 err = -ENOMEM;
3183 goto failed;
3184 }
3185
Johan Hedberg13928972013-03-15 17:07:00 -05003186 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3187
Johan Hedberg890ea892013-03-15 17:06:52 -05003188 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003189
3190 if (lmp_bredr_capable(hdev)) {
3191 update_name(&req);
3192 update_eir(&req);
3193 }
3194
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003195 /* The name is stored in the scan response data and so
3196 * no need to udpate the advertising data here.
3197 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003198 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003199 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003200
Johan Hedberg13928972013-03-15 17:07:00 -05003201 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003202 if (err < 0)
3203 mgmt_pending_remove(cmd);
3204
3205failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003206 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003207 return err;
3208}
3209
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003210static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003211 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003212{
Szymon Jancc35938b2011-03-22 13:12:21 +01003213 struct pending_cmd *cmd;
3214 int err;
3215
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003216 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003217
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003218 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003219
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003220 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003221 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003222 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003223 goto unlock;
3224 }
3225
Andre Guedes9a1a1992012-07-24 15:03:48 -03003226 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003227 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003228 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003229 goto unlock;
3230 }
3231
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003232 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003233 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003234 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003235 goto unlock;
3236 }
3237
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003238 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003239 if (!cmd) {
3240 err = -ENOMEM;
3241 goto unlock;
3242 }
3243
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003244 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3245 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3246 0, NULL);
3247 else
3248 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3249
Szymon Jancc35938b2011-03-22 13:12:21 +01003250 if (err < 0)
3251 mgmt_pending_remove(cmd);
3252
3253unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003254 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003255 return err;
3256}
3257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003258static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003260{
Szymon Janc2763eda2011-03-22 13:12:22 +01003261 int err;
3262
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003263 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003264
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003265 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003266
Marcel Holtmannec109112014-01-10 02:07:30 -08003267 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3268 struct mgmt_cp_add_remote_oob_data *cp = data;
3269 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003270
Marcel Holtmannec109112014-01-10 02:07:30 -08003271 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3272 cp->hash, cp->randomizer);
3273 if (err < 0)
3274 status = MGMT_STATUS_FAILED;
3275 else
3276 status = MGMT_STATUS_SUCCESS;
3277
3278 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3279 status, &cp->addr, sizeof(cp->addr));
3280 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3281 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3282 u8 status;
3283
3284 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3285 cp->hash192,
3286 cp->randomizer192,
3287 cp->hash256,
3288 cp->randomizer256);
3289 if (err < 0)
3290 status = MGMT_STATUS_FAILED;
3291 else
3292 status = MGMT_STATUS_SUCCESS;
3293
3294 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3295 status, &cp->addr, sizeof(cp->addr));
3296 } else {
3297 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3298 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3299 MGMT_STATUS_INVALID_PARAMS);
3300 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003301
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003302 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003303 return err;
3304}
3305
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003306static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003307 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003308{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003309 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003310 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003311 int err;
3312
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003313 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003314
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003315 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003316
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003317 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003318 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003319 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003320 else
Szymon Janca6785be2012-12-13 15:11:21 +01003321 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003322
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003323 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003324 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003325
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003326 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003327 return err;
3328}
3329
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003330static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3331{
3332 struct pending_cmd *cmd;
3333 u8 type;
3334 int err;
3335
3336 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3337
3338 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3339 if (!cmd)
3340 return -ENOENT;
3341
3342 type = hdev->discovery.type;
3343
3344 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3345 &type, sizeof(type));
3346 mgmt_pending_remove(cmd);
3347
3348 return err;
3349}
3350
Andre Guedes7c307722013-04-30 15:29:28 -03003351static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3352{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003353 unsigned long timeout = 0;
3354
Andre Guedes7c307722013-04-30 15:29:28 -03003355 BT_DBG("status %d", status);
3356
3357 if (status) {
3358 hci_dev_lock(hdev);
3359 mgmt_start_discovery_failed(hdev, status);
3360 hci_dev_unlock(hdev);
3361 return;
3362 }
3363
3364 hci_dev_lock(hdev);
3365 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3366 hci_dev_unlock(hdev);
3367
3368 switch (hdev->discovery.type) {
3369 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003370 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003371 break;
3372
3373 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003374 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003375 break;
3376
3377 case DISCOV_TYPE_BREDR:
3378 break;
3379
3380 default:
3381 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3382 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003383
3384 if (!timeout)
3385 return;
3386
3387 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003388}
3389
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003390static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003391 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003392{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003393 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003394 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003395 struct hci_cp_le_set_scan_param param_cp;
3396 struct hci_cp_le_set_scan_enable enable_cp;
3397 struct hci_cp_inquiry inq_cp;
3398 struct hci_request req;
3399 /* General inquiry access code (GIAC) */
3400 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003401 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003402 int err;
3403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003404 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003405
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003406 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003407
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003408 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003409 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003410 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003411 goto failed;
3412 }
3413
Andre Guedes642be6c2012-03-21 00:03:37 -03003414 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3415 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3416 MGMT_STATUS_BUSY);
3417 goto failed;
3418 }
3419
Johan Hedbergff9ef572012-01-04 14:23:45 +02003420 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003421 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003422 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003423 goto failed;
3424 }
3425
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003426 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003427 if (!cmd) {
3428 err = -ENOMEM;
3429 goto failed;
3430 }
3431
Andre Guedes4aab14e2012-02-17 20:39:36 -03003432 hdev->discovery.type = cp->type;
3433
Andre Guedes7c307722013-04-30 15:29:28 -03003434 hci_req_init(&req, hdev);
3435
Andre Guedes4aab14e2012-02-17 20:39:36 -03003436 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003437 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003438 status = mgmt_bredr_support(hdev);
3439 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003440 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003441 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003442 mgmt_pending_remove(cmd);
3443 goto failed;
3444 }
3445
Andre Guedes7c307722013-04-30 15:29:28 -03003446 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3447 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3448 MGMT_STATUS_BUSY);
3449 mgmt_pending_remove(cmd);
3450 goto failed;
3451 }
3452
3453 hci_inquiry_cache_flush(hdev);
3454
3455 memset(&inq_cp, 0, sizeof(inq_cp));
3456 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003457 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003458 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003459 break;
3460
3461 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003462 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003463 status = mgmt_le_support(hdev);
3464 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003465 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003466 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003467 mgmt_pending_remove(cmd);
3468 goto failed;
3469 }
3470
Andre Guedes7c307722013-04-30 15:29:28 -03003471 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003472 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003473 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3474 MGMT_STATUS_NOT_SUPPORTED);
3475 mgmt_pending_remove(cmd);
3476 goto failed;
3477 }
3478
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003479 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003480 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3481 MGMT_STATUS_REJECTED);
3482 mgmt_pending_remove(cmd);
3483 goto failed;
3484 }
3485
Andre Guedesc54c3862014-02-26 20:21:50 -03003486 /* If controller is scanning, it means the background scanning
3487 * is running. Thus, we should temporarily stop it in order to
3488 * set the discovery scanning parameters.
3489 */
3490 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3491 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003492
3493 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003494
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003495 /* All active scans will be done with either a resolvable
3496 * private address (when privacy feature has been enabled)
3497 * or unresolvable private address.
3498 */
3499 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003500 if (err < 0) {
3501 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3502 MGMT_STATUS_FAILED);
3503 mgmt_pending_remove(cmd);
3504 goto failed;
3505 }
3506
Andre Guedes7c307722013-04-30 15:29:28 -03003507 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003508 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3509 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003510 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003511 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3512 &param_cp);
3513
3514 memset(&enable_cp, 0, sizeof(enable_cp));
3515 enable_cp.enable = LE_SCAN_ENABLE;
3516 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3517 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3518 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003519 break;
3520
Andre Guedesf39799f2012-02-17 20:39:35 -03003521 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003522 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3523 MGMT_STATUS_INVALID_PARAMS);
3524 mgmt_pending_remove(cmd);
3525 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003526 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003527
Andre Guedes7c307722013-04-30 15:29:28 -03003528 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003529 if (err < 0)
3530 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003531 else
3532 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003533
3534failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003535 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003536 return err;
3537}
3538
Andre Guedes1183fdc2013-04-30 15:29:35 -03003539static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3540{
3541 struct pending_cmd *cmd;
3542 int err;
3543
3544 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3545 if (!cmd)
3546 return -ENOENT;
3547
3548 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3549 &hdev->discovery.type, sizeof(hdev->discovery.type));
3550 mgmt_pending_remove(cmd);
3551
3552 return err;
3553}
3554
Andre Guedes0e05bba2013-04-30 15:29:33 -03003555static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3556{
3557 BT_DBG("status %d", status);
3558
3559 hci_dev_lock(hdev);
3560
3561 if (status) {
3562 mgmt_stop_discovery_failed(hdev, status);
3563 goto unlock;
3564 }
3565
3566 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3567
3568unlock:
3569 hci_dev_unlock(hdev);
3570}
3571
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003572static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003573 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003574{
Johan Hedbergd9306502012-02-20 23:25:18 +02003575 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003576 struct pending_cmd *cmd;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003577 struct hci_cp_remote_name_req_cancel cp;
3578 struct inquiry_entry *e;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003579 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003580 int err;
3581
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003582 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003583
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003584 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003585
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003586 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003587 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003588 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3589 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003590 goto unlock;
3591 }
3592
3593 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003594 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003595 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3596 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003597 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003598 }
3599
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003600 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003601 if (!cmd) {
3602 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003603 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003604 }
3605
Andre Guedes0e05bba2013-04-30 15:29:33 -03003606 hci_req_init(&req, hdev);
3607
Andre Guedese0d9727e2012-03-20 15:15:36 -03003608 switch (hdev->discovery.state) {
3609 case DISCOVERY_FINDING:
Andre Guedes0e05bba2013-04-30 15:29:33 -03003610 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3611 hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
3612 } else {
3613 cancel_delayed_work(&hdev->le_scan_disable);
3614
Andre Guedesb1efcc22014-02-26 20:21:40 -03003615 hci_req_add_le_scan_disable(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003616 }
Andre Guedesc9ecc482012-03-15 16:52:08 -03003617
Andre Guedese0d9727e2012-03-20 15:15:36 -03003618 break;
3619
3620 case DISCOVERY_RESOLVING:
3621 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003622 NAME_PENDING);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003623 if (!e) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003624 mgmt_pending_remove(cmd);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003625 err = cmd_complete(sk, hdev->id,
3626 MGMT_OP_STOP_DISCOVERY, 0,
3627 &mgmt_cp->type,
3628 sizeof(mgmt_cp->type));
3629 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3630 goto unlock;
3631 }
3632
3633 bacpy(&cp.bdaddr, &e->data.bdaddr);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003634 hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
3635 &cp);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003636
3637 break;
3638
3639 default:
3640 BT_DBG("unknown discovery state %u", hdev->discovery.state);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003641
3642 mgmt_pending_remove(cmd);
3643 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
3644 MGMT_STATUS_FAILED, &mgmt_cp->type,
3645 sizeof(mgmt_cp->type));
3646 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003647 }
3648
Andre Guedes0e05bba2013-04-30 15:29:33 -03003649 err = hci_req_run(&req, stop_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003650 if (err < 0)
3651 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003652 else
3653 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003654
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003655unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003656 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003657 return err;
3658}
3659
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003660static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003661 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003662{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003663 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003664 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003665 int err;
3666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003667 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003668
Johan Hedberg561aafb2012-01-04 13:31:59 +02003669 hci_dev_lock(hdev);
3670
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003671 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003672 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3673 MGMT_STATUS_FAILED, &cp->addr,
3674 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003675 goto failed;
3676 }
3677
Johan Hedberga198e7b2012-02-17 14:27:06 +02003678 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003679 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003680 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3681 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3682 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003683 goto failed;
3684 }
3685
3686 if (cp->name_known) {
3687 e->name_state = NAME_KNOWN;
3688 list_del(&e->list);
3689 } else {
3690 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003691 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003692 }
3693
Johan Hedberge3846622013-01-09 15:29:33 +02003694 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3695 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003696
3697failed:
3698 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003699 return err;
3700}
3701
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003702static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003703 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003704{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003705 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003706 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003707 int err;
3708
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003709 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003710
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003711 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003712 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3713 MGMT_STATUS_INVALID_PARAMS,
3714 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003715
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003716 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003717
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003718 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003719 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003720 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003721 else
Szymon Janca6785be2012-12-13 15:11:21 +01003722 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003724 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003725 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003726
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003727 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003728
3729 return err;
3730}
3731
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003732static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003733 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003734{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003735 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003736 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003737 int err;
3738
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003739 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003740
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003741 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003742 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3743 MGMT_STATUS_INVALID_PARAMS,
3744 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003745
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003746 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003747
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003748 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003749 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003750 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003751 else
Szymon Janca6785be2012-12-13 15:11:21 +01003752 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003753
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003754 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003755 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003756
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003757 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003758
3759 return err;
3760}
3761
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003762static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3763 u16 len)
3764{
3765 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003766 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003767 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003768 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003769
3770 BT_DBG("%s", hdev->name);
3771
Szymon Jancc72d4b82012-03-16 16:02:57 +01003772 source = __le16_to_cpu(cp->source);
3773
3774 if (source > 0x0002)
3775 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3776 MGMT_STATUS_INVALID_PARAMS);
3777
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003778 hci_dev_lock(hdev);
3779
Szymon Jancc72d4b82012-03-16 16:02:57 +01003780 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003781 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3782 hdev->devid_product = __le16_to_cpu(cp->product);
3783 hdev->devid_version = __le16_to_cpu(cp->version);
3784
3785 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3786
Johan Hedberg890ea892013-03-15 17:06:52 -05003787 hci_req_init(&req, hdev);
3788 update_eir(&req);
3789 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003790
3791 hci_dev_unlock(hdev);
3792
3793 return err;
3794}
3795
Johan Hedberg4375f102013-09-25 13:26:10 +03003796static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3797{
3798 struct cmd_lookup match = { NULL, hdev };
3799
3800 if (status) {
3801 u8 mgmt_err = mgmt_status(status);
3802
3803 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3804 cmd_status_rsp, &mgmt_err);
3805 return;
3806 }
3807
3808 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3809 &match);
3810
3811 new_settings(hdev, match.sk);
3812
3813 if (match.sk)
3814 sock_put(match.sk);
3815}
3816
Marcel Holtmann21b51872013-10-10 09:47:53 -07003817static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3818 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003819{
3820 struct mgmt_mode *cp = data;
3821 struct pending_cmd *cmd;
3822 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003823 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003824 int err;
3825
3826 BT_DBG("request for %s", hdev->name);
3827
Johan Hedberge6fe7982013-10-02 15:45:22 +03003828 status = mgmt_le_support(hdev);
3829 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003830 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003831 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003832
3833 if (cp->val != 0x00 && cp->val != 0x01)
3834 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3835 MGMT_STATUS_INVALID_PARAMS);
3836
3837 hci_dev_lock(hdev);
3838
3839 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003840 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003841
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003842 /* The following conditions are ones which mean that we should
3843 * not do any HCI communication but directly send a mgmt
3844 * response to user space (after toggling the flag if
3845 * necessary).
3846 */
3847 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003848 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003849 bool changed = false;
3850
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003851 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3852 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003853 changed = true;
3854 }
3855
3856 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3857 if (err < 0)
3858 goto unlock;
3859
3860 if (changed)
3861 err = new_settings(hdev, sk);
3862
3863 goto unlock;
3864 }
3865
3866 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3867 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3868 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3869 MGMT_STATUS_BUSY);
3870 goto unlock;
3871 }
3872
3873 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3874 if (!cmd) {
3875 err = -ENOMEM;
3876 goto unlock;
3877 }
3878
3879 hci_req_init(&req, hdev);
3880
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003881 if (val)
3882 enable_advertising(&req);
3883 else
3884 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003885
3886 err = hci_req_run(&req, set_advertising_complete);
3887 if (err < 0)
3888 mgmt_pending_remove(cmd);
3889
3890unlock:
3891 hci_dev_unlock(hdev);
3892 return err;
3893}
3894
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003895static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3896 void *data, u16 len)
3897{
3898 struct mgmt_cp_set_static_address *cp = data;
3899 int err;
3900
3901 BT_DBG("%s", hdev->name);
3902
Marcel Holtmann62af4442013-10-02 22:10:32 -07003903 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003904 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003905 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003906
3907 if (hdev_is_powered(hdev))
3908 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3909 MGMT_STATUS_REJECTED);
3910
3911 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3912 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3913 return cmd_status(sk, hdev->id,
3914 MGMT_OP_SET_STATIC_ADDRESS,
3915 MGMT_STATUS_INVALID_PARAMS);
3916
3917 /* Two most significant bits shall be set */
3918 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3919 return cmd_status(sk, hdev->id,
3920 MGMT_OP_SET_STATIC_ADDRESS,
3921 MGMT_STATUS_INVALID_PARAMS);
3922 }
3923
3924 hci_dev_lock(hdev);
3925
3926 bacpy(&hdev->static_addr, &cp->bdaddr);
3927
3928 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3929
3930 hci_dev_unlock(hdev);
3931
3932 return err;
3933}
3934
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003935static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3936 void *data, u16 len)
3937{
3938 struct mgmt_cp_set_scan_params *cp = data;
3939 __u16 interval, window;
3940 int err;
3941
3942 BT_DBG("%s", hdev->name);
3943
3944 if (!lmp_le_capable(hdev))
3945 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3946 MGMT_STATUS_NOT_SUPPORTED);
3947
3948 interval = __le16_to_cpu(cp->interval);
3949
3950 if (interval < 0x0004 || interval > 0x4000)
3951 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3952 MGMT_STATUS_INVALID_PARAMS);
3953
3954 window = __le16_to_cpu(cp->window);
3955
3956 if (window < 0x0004 || window > 0x4000)
3957 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3958 MGMT_STATUS_INVALID_PARAMS);
3959
Marcel Holtmann899e1072013-10-14 09:55:32 -07003960 if (window > interval)
3961 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3962 MGMT_STATUS_INVALID_PARAMS);
3963
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003964 hci_dev_lock(hdev);
3965
3966 hdev->le_scan_interval = interval;
3967 hdev->le_scan_window = window;
3968
3969 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3970
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003971 /* If background scan is running, restart it so new parameters are
3972 * loaded.
3973 */
3974 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
3975 hdev->discovery.state == DISCOVERY_STOPPED) {
3976 struct hci_request req;
3977
3978 hci_req_init(&req, hdev);
3979
3980 hci_req_add_le_scan_disable(&req);
3981 hci_req_add_le_passive_scan(&req);
3982
3983 hci_req_run(&req, NULL);
3984 }
3985
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003986 hci_dev_unlock(hdev);
3987
3988 return err;
3989}
3990
Johan Hedberg33e38b32013-03-15 17:07:05 -05003991static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3992{
3993 struct pending_cmd *cmd;
3994
3995 BT_DBG("status 0x%02x", status);
3996
3997 hci_dev_lock(hdev);
3998
3999 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4000 if (!cmd)
4001 goto unlock;
4002
4003 if (status) {
4004 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4005 mgmt_status(status));
4006 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004007 struct mgmt_mode *cp = cmd->param;
4008
4009 if (cp->val)
4010 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4011 else
4012 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4013
Johan Hedberg33e38b32013-03-15 17:07:05 -05004014 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4015 new_settings(hdev, cmd->sk);
4016 }
4017
4018 mgmt_pending_remove(cmd);
4019
4020unlock:
4021 hci_dev_unlock(hdev);
4022}
4023
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004024static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004025 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004026{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004027 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004028 struct pending_cmd *cmd;
4029 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004030 int err;
4031
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004032 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004033
Johan Hedberg56f87902013-10-02 13:43:13 +03004034 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4035 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004036 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4037 MGMT_STATUS_NOT_SUPPORTED);
4038
Johan Hedberga7e80f22013-01-09 16:05:19 +02004039 if (cp->val != 0x00 && cp->val != 0x01)
4040 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4041 MGMT_STATUS_INVALID_PARAMS);
4042
Johan Hedberg5400c042012-02-21 16:40:33 +02004043 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004044 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004045 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004046
4047 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004048 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004049 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004050
4051 hci_dev_lock(hdev);
4052
Johan Hedberg05cbf292013-03-15 17:07:07 -05004053 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4054 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4055 MGMT_STATUS_BUSY);
4056 goto unlock;
4057 }
4058
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004059 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4060 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4061 hdev);
4062 goto unlock;
4063 }
4064
Johan Hedberg33e38b32013-03-15 17:07:05 -05004065 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4066 data, len);
4067 if (!cmd) {
4068 err = -ENOMEM;
4069 goto unlock;
4070 }
4071
4072 hci_req_init(&req, hdev);
4073
Johan Hedberg406d7802013-03-15 17:07:09 -05004074 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004075
4076 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004077 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004078 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004079 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004080 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004081 }
4082
Johan Hedberg33e38b32013-03-15 17:07:05 -05004083unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004084 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004085
Antti Julkuf6422ec2011-06-22 13:11:56 +03004086 return err;
4087}
4088
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004089static void set_bredr_scan(struct hci_request *req)
4090{
4091 struct hci_dev *hdev = req->hdev;
4092 u8 scan = 0;
4093
4094 /* Ensure that fast connectable is disabled. This function will
4095 * not do anything if the page scan parameters are already what
4096 * they should be.
4097 */
4098 write_fast_connectable(req, false);
4099
4100 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4101 scan |= SCAN_PAGE;
4102 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4103 scan |= SCAN_INQUIRY;
4104
4105 if (scan)
4106 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4107}
4108
Johan Hedberg0663ca22013-10-02 13:43:14 +03004109static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4110{
4111 struct pending_cmd *cmd;
4112
4113 BT_DBG("status 0x%02x", status);
4114
4115 hci_dev_lock(hdev);
4116
4117 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4118 if (!cmd)
4119 goto unlock;
4120
4121 if (status) {
4122 u8 mgmt_err = mgmt_status(status);
4123
4124 /* We need to restore the flag if related HCI commands
4125 * failed.
4126 */
4127 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4128
4129 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4130 } else {
4131 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4132 new_settings(hdev, cmd->sk);
4133 }
4134
4135 mgmt_pending_remove(cmd);
4136
4137unlock:
4138 hci_dev_unlock(hdev);
4139}
4140
4141static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4142{
4143 struct mgmt_mode *cp = data;
4144 struct pending_cmd *cmd;
4145 struct hci_request req;
4146 int err;
4147
4148 BT_DBG("request for %s", hdev->name);
4149
4150 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4151 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4152 MGMT_STATUS_NOT_SUPPORTED);
4153
4154 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4155 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4156 MGMT_STATUS_REJECTED);
4157
4158 if (cp->val != 0x00 && cp->val != 0x01)
4159 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4160 MGMT_STATUS_INVALID_PARAMS);
4161
4162 hci_dev_lock(hdev);
4163
4164 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4165 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4166 goto unlock;
4167 }
4168
4169 if (!hdev_is_powered(hdev)) {
4170 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004171 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4172 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4173 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4174 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4175 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4176 }
4177
4178 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4179
4180 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4181 if (err < 0)
4182 goto unlock;
4183
4184 err = new_settings(hdev, sk);
4185 goto unlock;
4186 }
4187
4188 /* Reject disabling when powered on */
4189 if (!cp->val) {
4190 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4191 MGMT_STATUS_REJECTED);
4192 goto unlock;
4193 }
4194
4195 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4196 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4197 MGMT_STATUS_BUSY);
4198 goto unlock;
4199 }
4200
4201 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4202 if (!cmd) {
4203 err = -ENOMEM;
4204 goto unlock;
4205 }
4206
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004207 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004208 * generates the correct flags.
4209 */
4210 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4211
4212 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004213
4214 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4215 set_bredr_scan(&req);
4216
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004217 /* Since only the advertising data flags will change, there
4218 * is no need to update the scan response data.
4219 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004220 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004221
Johan Hedberg0663ca22013-10-02 13:43:14 +03004222 err = hci_req_run(&req, set_bredr_complete);
4223 if (err < 0)
4224 mgmt_pending_remove(cmd);
4225
4226unlock:
4227 hci_dev_unlock(hdev);
4228 return err;
4229}
4230
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004231static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4232 void *data, u16 len)
4233{
4234 struct mgmt_mode *cp = data;
4235 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004236 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004237 int err;
4238
4239 BT_DBG("request for %s", hdev->name);
4240
4241 status = mgmt_bredr_support(hdev);
4242 if (status)
4243 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4244 status);
4245
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004246 if (!lmp_sc_capable(hdev) &&
4247 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004248 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4249 MGMT_STATUS_NOT_SUPPORTED);
4250
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004251 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004252 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4253 MGMT_STATUS_INVALID_PARAMS);
4254
4255 hci_dev_lock(hdev);
4256
4257 if (!hdev_is_powered(hdev)) {
4258 bool changed;
4259
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004260 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004261 changed = !test_and_set_bit(HCI_SC_ENABLED,
4262 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004263 if (cp->val == 0x02)
4264 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4265 else
4266 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4267 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004268 changed = test_and_clear_bit(HCI_SC_ENABLED,
4269 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004270 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4271 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004272
4273 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4274 if (err < 0)
4275 goto failed;
4276
4277 if (changed)
4278 err = new_settings(hdev, sk);
4279
4280 goto failed;
4281 }
4282
4283 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4284 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4285 MGMT_STATUS_BUSY);
4286 goto failed;
4287 }
4288
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004289 val = !!cp->val;
4290
4291 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4292 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004293 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4294 goto failed;
4295 }
4296
4297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4298 if (!cmd) {
4299 err = -ENOMEM;
4300 goto failed;
4301 }
4302
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004303 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004304 if (err < 0) {
4305 mgmt_pending_remove(cmd);
4306 goto failed;
4307 }
4308
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004309 if (cp->val == 0x02)
4310 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4311 else
4312 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4313
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004314failed:
4315 hci_dev_unlock(hdev);
4316 return err;
4317}
4318
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004319static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4320 void *data, u16 len)
4321{
4322 struct mgmt_mode *cp = data;
4323 bool changed;
4324 int err;
4325
4326 BT_DBG("request for %s", hdev->name);
4327
4328 if (cp->val != 0x00 && cp->val != 0x01)
4329 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4330 MGMT_STATUS_INVALID_PARAMS);
4331
4332 hci_dev_lock(hdev);
4333
4334 if (cp->val)
4335 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4336 else
4337 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4338
4339 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4340 if (err < 0)
4341 goto unlock;
4342
4343 if (changed)
4344 err = new_settings(hdev, sk);
4345
4346unlock:
4347 hci_dev_unlock(hdev);
4348 return err;
4349}
4350
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004351static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4352 u16 len)
4353{
4354 struct mgmt_cp_set_privacy *cp = cp_data;
4355 bool changed;
4356 int err;
4357
4358 BT_DBG("request for %s", hdev->name);
4359
4360 if (!lmp_le_capable(hdev))
4361 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4362 MGMT_STATUS_NOT_SUPPORTED);
4363
4364 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4365 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4366 MGMT_STATUS_INVALID_PARAMS);
4367
4368 if (hdev_is_powered(hdev))
4369 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4370 MGMT_STATUS_REJECTED);
4371
4372 hci_dev_lock(hdev);
4373
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004374 /* If user space supports this command it is also expected to
4375 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4376 */
4377 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4378
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004379 if (cp->privacy) {
4380 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4381 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4382 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4383 } else {
4384 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4385 memset(hdev->irk, 0, sizeof(hdev->irk));
4386 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4387 }
4388
4389 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4390 if (err < 0)
4391 goto unlock;
4392
4393 if (changed)
4394 err = new_settings(hdev, sk);
4395
4396unlock:
4397 hci_dev_unlock(hdev);
4398 return err;
4399}
4400
Johan Hedberg41edf162014-02-18 10:19:35 +02004401static bool irk_is_valid(struct mgmt_irk_info *irk)
4402{
4403 switch (irk->addr.type) {
4404 case BDADDR_LE_PUBLIC:
4405 return true;
4406
4407 case BDADDR_LE_RANDOM:
4408 /* Two most significant bits shall be set */
4409 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4410 return false;
4411 return true;
4412 }
4413
4414 return false;
4415}
4416
4417static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4418 u16 len)
4419{
4420 struct mgmt_cp_load_irks *cp = cp_data;
4421 u16 irk_count, expected_len;
4422 int i, err;
4423
4424 BT_DBG("request for %s", hdev->name);
4425
4426 if (!lmp_le_capable(hdev))
4427 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4428 MGMT_STATUS_NOT_SUPPORTED);
4429
4430 irk_count = __le16_to_cpu(cp->irk_count);
4431
4432 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4433 if (expected_len != len) {
4434 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004435 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004436 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4437 MGMT_STATUS_INVALID_PARAMS);
4438 }
4439
4440 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4441
4442 for (i = 0; i < irk_count; i++) {
4443 struct mgmt_irk_info *key = &cp->irks[i];
4444
4445 if (!irk_is_valid(key))
4446 return cmd_status(sk, hdev->id,
4447 MGMT_OP_LOAD_IRKS,
4448 MGMT_STATUS_INVALID_PARAMS);
4449 }
4450
4451 hci_dev_lock(hdev);
4452
4453 hci_smp_irks_clear(hdev);
4454
4455 for (i = 0; i < irk_count; i++) {
4456 struct mgmt_irk_info *irk = &cp->irks[i];
4457 u8 addr_type;
4458
4459 if (irk->addr.type == BDADDR_LE_PUBLIC)
4460 addr_type = ADDR_LE_DEV_PUBLIC;
4461 else
4462 addr_type = ADDR_LE_DEV_RANDOM;
4463
4464 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4465 BDADDR_ANY);
4466 }
4467
4468 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4469
4470 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4471
4472 hci_dev_unlock(hdev);
4473
4474 return err;
4475}
4476
Johan Hedberg3f706b72013-01-20 14:27:16 +02004477static bool ltk_is_valid(struct mgmt_ltk_info *key)
4478{
4479 if (key->master != 0x00 && key->master != 0x01)
4480 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004481
4482 switch (key->addr.type) {
4483 case BDADDR_LE_PUBLIC:
4484 return true;
4485
4486 case BDADDR_LE_RANDOM:
4487 /* Two most significant bits shall be set */
4488 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4489 return false;
4490 return true;
4491 }
4492
4493 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004494}
4495
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004496static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004497 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004498{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004499 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4500 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004501 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004502
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004503 BT_DBG("request for %s", hdev->name);
4504
4505 if (!lmp_le_capable(hdev))
4506 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4507 MGMT_STATUS_NOT_SUPPORTED);
4508
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004509 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004510
4511 expected_len = sizeof(*cp) + key_count *
4512 sizeof(struct mgmt_ltk_info);
4513 if (expected_len != len) {
4514 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004515 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004516 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004517 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004518 }
4519
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004520 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004521
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004522 for (i = 0; i < key_count; i++) {
4523 struct mgmt_ltk_info *key = &cp->keys[i];
4524
Johan Hedberg3f706b72013-01-20 14:27:16 +02004525 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004526 return cmd_status(sk, hdev->id,
4527 MGMT_OP_LOAD_LONG_TERM_KEYS,
4528 MGMT_STATUS_INVALID_PARAMS);
4529 }
4530
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004531 hci_dev_lock(hdev);
4532
4533 hci_smp_ltks_clear(hdev);
4534
4535 for (i = 0; i < key_count; i++) {
4536 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004537 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004538
4539 if (key->addr.type == BDADDR_LE_PUBLIC)
4540 addr_type = ADDR_LE_DEV_PUBLIC;
4541 else
4542 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004543
4544 if (key->master)
4545 type = HCI_SMP_LTK;
4546 else
4547 type = HCI_SMP_LTK_SLAVE;
4548
Johan Hedberg61b43352014-05-29 19:36:53 +03004549 switch (key->type) {
4550 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004551 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004552 break;
4553 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004554 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004555 break;
4556 default:
4557 continue;
4558 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004559
Johan Hedberg35d70272014-02-19 14:57:47 +02004560 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004561 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004562 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004563 }
4564
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004565 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4566 NULL, 0);
4567
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004568 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004569
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004570 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004571}
4572
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004573struct cmd_conn_lookup {
4574 struct hci_conn *conn;
4575 bool valid_tx_power;
4576 u8 mgmt_status;
4577};
4578
4579static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4580{
4581 struct cmd_conn_lookup *match = data;
4582 struct mgmt_cp_get_conn_info *cp;
4583 struct mgmt_rp_get_conn_info rp;
4584 struct hci_conn *conn = cmd->user_data;
4585
4586 if (conn != match->conn)
4587 return;
4588
4589 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4590
4591 memset(&rp, 0, sizeof(rp));
4592 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4593 rp.addr.type = cp->addr.type;
4594
4595 if (!match->mgmt_status) {
4596 rp.rssi = conn->rssi;
4597
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004598 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004599 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004600 rp.max_tx_power = conn->max_tx_power;
4601 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004602 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004603 rp.max_tx_power = HCI_TX_POWER_INVALID;
4604 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004605 }
4606
4607 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4608 match->mgmt_status, &rp, sizeof(rp));
4609
4610 hci_conn_drop(conn);
4611
4612 mgmt_pending_remove(cmd);
4613}
4614
4615static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4616{
4617 struct hci_cp_read_rssi *cp;
4618 struct hci_conn *conn;
4619 struct cmd_conn_lookup match;
4620 u16 handle;
4621
4622 BT_DBG("status 0x%02x", status);
4623
4624 hci_dev_lock(hdev);
4625
4626 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004627 * otherwise we assume it's not valid. At the moment we assume that
4628 * either both or none of current and max values are valid to keep code
4629 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004630 */
4631 match.valid_tx_power = !status;
4632
4633 /* Commands sent in request are either Read RSSI or Read Transmit Power
4634 * Level so we check which one was last sent to retrieve connection
4635 * handle. Both commands have handle as first parameter so it's safe to
4636 * cast data on the same command struct.
4637 *
4638 * First command sent is always Read RSSI and we fail only if it fails.
4639 * In other case we simply override error to indicate success as we
4640 * already remembered if TX power value is actually valid.
4641 */
4642 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4643 if (!cp) {
4644 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4645 status = 0;
4646 }
4647
4648 if (!cp) {
4649 BT_ERR("invalid sent_cmd in response");
4650 goto unlock;
4651 }
4652
4653 handle = __le16_to_cpu(cp->handle);
4654 conn = hci_conn_hash_lookup_handle(hdev, handle);
4655 if (!conn) {
4656 BT_ERR("unknown handle (%d) in response", handle);
4657 goto unlock;
4658 }
4659
4660 match.conn = conn;
4661 match.mgmt_status = mgmt_status(status);
4662
4663 /* Cache refresh is complete, now reply for mgmt request for given
4664 * connection only.
4665 */
4666 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4667 get_conn_info_complete, &match);
4668
4669unlock:
4670 hci_dev_unlock(hdev);
4671}
4672
4673static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4674 u16 len)
4675{
4676 struct mgmt_cp_get_conn_info *cp = data;
4677 struct mgmt_rp_get_conn_info rp;
4678 struct hci_conn *conn;
4679 unsigned long conn_info_age;
4680 int err = 0;
4681
4682 BT_DBG("%s", hdev->name);
4683
4684 memset(&rp, 0, sizeof(rp));
4685 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4686 rp.addr.type = cp->addr.type;
4687
4688 if (!bdaddr_type_is_valid(cp->addr.type))
4689 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4690 MGMT_STATUS_INVALID_PARAMS,
4691 &rp, sizeof(rp));
4692
4693 hci_dev_lock(hdev);
4694
4695 if (!hdev_is_powered(hdev)) {
4696 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4697 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4698 goto unlock;
4699 }
4700
4701 if (cp->addr.type == BDADDR_BREDR)
4702 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4703 &cp->addr.bdaddr);
4704 else
4705 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4706
4707 if (!conn || conn->state != BT_CONNECTED) {
4708 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4709 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4710 goto unlock;
4711 }
4712
4713 /* To avoid client trying to guess when to poll again for information we
4714 * calculate conn info age as random value between min/max set in hdev.
4715 */
4716 conn_info_age = hdev->conn_info_min_age +
4717 prandom_u32_max(hdev->conn_info_max_age -
4718 hdev->conn_info_min_age);
4719
4720 /* Query controller to refresh cached values if they are too old or were
4721 * never read.
4722 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004723 if (time_after(jiffies, conn->conn_info_timestamp +
4724 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004725 !conn->conn_info_timestamp) {
4726 struct hci_request req;
4727 struct hci_cp_read_tx_power req_txp_cp;
4728 struct hci_cp_read_rssi req_rssi_cp;
4729 struct pending_cmd *cmd;
4730
4731 hci_req_init(&req, hdev);
4732 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4733 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4734 &req_rssi_cp);
4735
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004736 /* For LE links TX power does not change thus we don't need to
4737 * query for it once value is known.
4738 */
4739 if (!bdaddr_type_is_le(cp->addr.type) ||
4740 conn->tx_power == HCI_TX_POWER_INVALID) {
4741 req_txp_cp.handle = cpu_to_le16(conn->handle);
4742 req_txp_cp.type = 0x00;
4743 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4744 sizeof(req_txp_cp), &req_txp_cp);
4745 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004746
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004747 /* Max TX power needs to be read only once per connection */
4748 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4749 req_txp_cp.handle = cpu_to_le16(conn->handle);
4750 req_txp_cp.type = 0x01;
4751 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4752 sizeof(req_txp_cp), &req_txp_cp);
4753 }
4754
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004755 err = hci_req_run(&req, conn_info_refresh_complete);
4756 if (err < 0)
4757 goto unlock;
4758
4759 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4760 data, len);
4761 if (!cmd) {
4762 err = -ENOMEM;
4763 goto unlock;
4764 }
4765
4766 hci_conn_hold(conn);
4767 cmd->user_data = conn;
4768
4769 conn->conn_info_timestamp = jiffies;
4770 } else {
4771 /* Cache is valid, just reply with values cached in hci_conn */
4772 rp.rssi = conn->rssi;
4773 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004774 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004775
4776 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4777 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4778 }
4779
4780unlock:
4781 hci_dev_unlock(hdev);
4782 return err;
4783}
4784
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004785static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004786 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4787 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004788 bool var_len;
4789 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004790} mgmt_handlers[] = {
4791 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004792 { read_version, false, MGMT_READ_VERSION_SIZE },
4793 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4794 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4795 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4796 { set_powered, false, MGMT_SETTING_SIZE },
4797 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4798 { set_connectable, false, MGMT_SETTING_SIZE },
4799 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4800 { set_pairable, false, MGMT_SETTING_SIZE },
4801 { set_link_security, false, MGMT_SETTING_SIZE },
4802 { set_ssp, false, MGMT_SETTING_SIZE },
4803 { set_hs, false, MGMT_SETTING_SIZE },
4804 { set_le, false, MGMT_SETTING_SIZE },
4805 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4806 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4807 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4808 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4809 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4810 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4811 { disconnect, false, MGMT_DISCONNECT_SIZE },
4812 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4813 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4814 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4815 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4816 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4817 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4818 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4819 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4820 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4821 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4822 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4823 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004824 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004825 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4826 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4827 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4828 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4829 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4830 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004831 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004832 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004833 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004834 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004835 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004836 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004837 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004838 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004839 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004840 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004841};
4842
4843
Johan Hedberg03811012010-12-08 00:21:06 +02004844int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4845{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004846 void *buf;
4847 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004848 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004849 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004850 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004851 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004852 int err;
4853
4854 BT_DBG("got %zu bytes", msglen);
4855
4856 if (msglen < sizeof(*hdr))
4857 return -EINVAL;
4858
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004859 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004860 if (!buf)
4861 return -ENOMEM;
4862
4863 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4864 err = -EFAULT;
4865 goto done;
4866 }
4867
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004868 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004869 opcode = __le16_to_cpu(hdr->opcode);
4870 index = __le16_to_cpu(hdr->index);
4871 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004872
4873 if (len != msglen - sizeof(*hdr)) {
4874 err = -EINVAL;
4875 goto done;
4876 }
4877
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004878 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004879 hdev = hci_dev_get(index);
4880 if (!hdev) {
4881 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004882 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004883 goto done;
4884 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004885
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004886 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4887 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004888 err = cmd_status(sk, index, opcode,
4889 MGMT_STATUS_INVALID_INDEX);
4890 goto done;
4891 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004892 }
4893
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004894 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004895 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004896 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004897 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004898 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004899 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004900 }
4901
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004902 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004903 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004904 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004905 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004906 goto done;
4907 }
4908
Johan Hedbergbe22b542012-03-01 22:24:41 +02004909 handler = &mgmt_handlers[opcode];
4910
4911 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004912 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004913 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004914 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004915 goto done;
4916 }
4917
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004918 if (hdev)
4919 mgmt_init_hdev(sk, hdev);
4920
4921 cp = buf + sizeof(*hdr);
4922
Johan Hedbergbe22b542012-03-01 22:24:41 +02004923 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004924 if (err < 0)
4925 goto done;
4926
Johan Hedberg03811012010-12-08 00:21:06 +02004927 err = msglen;
4928
4929done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004930 if (hdev)
4931 hci_dev_put(hdev);
4932
Johan Hedberg03811012010-12-08 00:21:06 +02004933 kfree(buf);
4934 return err;
4935}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004936
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004937void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004938{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004939 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004940 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004941
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004942 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004943}
4944
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004945void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004946{
Johan Hedberg5f159032012-03-02 03:13:19 +02004947 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004948
Marcel Holtmann1514b892013-10-06 08:25:01 -07004949 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004950 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004951
Johan Hedberg744cf192011-11-08 20:40:14 +02004952 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004953
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004954 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004955}
4956
Andre Guedes6046dc32014-02-26 20:21:51 -03004957/* This function requires the caller holds hdev->lock */
4958static void restart_le_auto_conns(struct hci_dev *hdev)
4959{
4960 struct hci_conn_params *p;
4961
4962 list_for_each_entry(p, &hdev->le_conn_params, list) {
4963 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4964 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4965 }
4966}
4967
Johan Hedberg229ab392013-03-15 17:06:53 -05004968static void powered_complete(struct hci_dev *hdev, u8 status)
4969{
4970 struct cmd_lookup match = { NULL, hdev };
4971
4972 BT_DBG("status 0x%02x", status);
4973
4974 hci_dev_lock(hdev);
4975
Andre Guedes6046dc32014-02-26 20:21:51 -03004976 restart_le_auto_conns(hdev);
4977
Johan Hedberg229ab392013-03-15 17:06:53 -05004978 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4979
4980 new_settings(hdev, match.sk);
4981
4982 hci_dev_unlock(hdev);
4983
4984 if (match.sk)
4985 sock_put(match.sk);
4986}
4987
Johan Hedberg70da6242013-03-15 17:06:51 -05004988static int powered_update_hci(struct hci_dev *hdev)
4989{
Johan Hedberg890ea892013-03-15 17:06:52 -05004990 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004991 u8 link_sec;
4992
Johan Hedberg890ea892013-03-15 17:06:52 -05004993 hci_req_init(&req, hdev);
4994
Johan Hedberg70da6242013-03-15 17:06:51 -05004995 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4996 !lmp_host_ssp_capable(hdev)) {
4997 u8 ssp = 1;
4998
Johan Hedberg890ea892013-03-15 17:06:52 -05004999 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005000 }
5001
Johan Hedbergc73eee92013-04-19 18:35:21 +03005002 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5003 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005004 struct hci_cp_write_le_host_supported cp;
5005
5006 cp.le = 1;
5007 cp.simul = lmp_le_br_capable(hdev);
5008
5009 /* Check first if we already have the right
5010 * host state (host features set)
5011 */
5012 if (cp.le != lmp_host_le_capable(hdev) ||
5013 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005014 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5015 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005016 }
5017
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005018 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005019 /* Make sure the controller has a good default for
5020 * advertising data. This also applies to the case
5021 * where BR/EDR was toggled during the AUTO_OFF phase.
5022 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005023 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005024 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005025 update_scan_rsp_data(&req);
5026 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005027
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005028 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5029 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005030 }
5031
Johan Hedberg70da6242013-03-15 17:06:51 -05005032 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5033 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005034 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5035 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005036
5037 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005038 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5039 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005040 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005041 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005042 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005043 }
5044
Johan Hedberg229ab392013-03-15 17:06:53 -05005045 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005046}
5047
Johan Hedberg744cf192011-11-08 20:40:14 +02005048int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005049{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005050 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005051 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5052 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005053 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005054
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005055 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5056 return 0;
5057
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005058 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005059 if (powered_update_hci(hdev) == 0)
5060 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005061
Johan Hedberg229ab392013-03-15 17:06:53 -05005062 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5063 &match);
5064 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005065 }
5066
Johan Hedberg229ab392013-03-15 17:06:53 -05005067 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5068 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5069
5070 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5071 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5072 zero_cod, sizeof(zero_cod), NULL);
5073
5074new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005075 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005076
5077 if (match.sk)
5078 sock_put(match.sk);
5079
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005080 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005081}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005082
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005083void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005084{
5085 struct pending_cmd *cmd;
5086 u8 status;
5087
5088 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5089 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005090 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005091
5092 if (err == -ERFKILL)
5093 status = MGMT_STATUS_RFKILLED;
5094 else
5095 status = MGMT_STATUS_FAILED;
5096
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005097 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005098
5099 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005100}
5101
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005102void mgmt_discoverable_timeout(struct hci_dev *hdev)
5103{
5104 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005105
5106 hci_dev_lock(hdev);
5107
5108 /* When discoverable timeout triggers, then just make sure
5109 * the limited discoverable flag is cleared. Even in the case
5110 * of a timeout triggered from general discoverable, it is
5111 * safe to unconditionally clear the flag.
5112 */
5113 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005114 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005115
5116 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005117 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5118 u8 scan = SCAN_PAGE;
5119 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5120 sizeof(scan), &scan);
5121 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005122 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005123 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005124 hci_req_run(&req, NULL);
5125
5126 hdev->discov_timeout = 0;
5127
Johan Hedberg9a43e252013-10-20 19:00:07 +03005128 new_settings(hdev, NULL);
5129
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005130 hci_dev_unlock(hdev);
5131}
5132
Marcel Holtmann86a75642013-10-15 06:33:54 -07005133void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005134{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005135 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005136
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005137 /* Nothing needed here if there's a pending command since that
5138 * commands request completion callback takes care of everything
5139 * necessary.
5140 */
5141 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005142 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005143
Johan Hedbergbd107992014-02-24 14:52:19 +02005144 /* Powering off may clear the scan mode - don't let that interfere */
5145 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5146 return;
5147
Johan Hedberg9a43e252013-10-20 19:00:07 +03005148 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005149 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005150 } else {
5151 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005152 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005153 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005154
Johan Hedberg9a43e252013-10-20 19:00:07 +03005155 if (changed) {
5156 struct hci_request req;
5157
5158 /* In case this change in discoverable was triggered by
5159 * a disabling of connectable there could be a need to
5160 * update the advertising flags.
5161 */
5162 hci_req_init(&req, hdev);
5163 update_adv_data(&req);
5164 hci_req_run(&req, NULL);
5165
Marcel Holtmann86a75642013-10-15 06:33:54 -07005166 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005167 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005168}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005169
Marcel Holtmanna3309162013-10-15 06:33:55 -07005170void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005171{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005172 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005173
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005174 /* Nothing needed here if there's a pending command since that
5175 * commands request completion callback takes care of everything
5176 * necessary.
5177 */
5178 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005179 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005180
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005181 /* Powering off may clear the scan mode - don't let that interfere */
5182 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5183 return;
5184
Marcel Holtmanna3309162013-10-15 06:33:55 -07005185 if (connectable)
5186 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5187 else
5188 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005189
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005190 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005191 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005192}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005193
Johan Hedberg778b2352014-02-24 14:52:17 +02005194void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5195{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005196 /* Powering off may stop advertising - don't let that interfere */
5197 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5198 return;
5199
Johan Hedberg778b2352014-02-24 14:52:17 +02005200 if (advertising)
5201 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5202 else
5203 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5204}
5205
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005206void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005207{
Johan Hedbergca69b792011-11-11 18:10:00 +02005208 u8 mgmt_err = mgmt_status(status);
5209
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005210 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005211 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005212 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005213
5214 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005215 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005216 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005217}
5218
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005219void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5220 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005221{
Johan Hedberg86742e12011-11-07 23:13:38 +02005222 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005223
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005224 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005225
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005226 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005227 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005228 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005229 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005230 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005231 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005232
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005233 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005234}
Johan Hedbergf7520542011-01-20 12:34:39 +02005235
Johan Hedbergd7b25452014-05-23 13:19:53 +03005236static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5237{
5238 if (ltk->authenticated)
5239 return MGMT_LTK_AUTHENTICATED;
5240
5241 return MGMT_LTK_UNAUTHENTICATED;
5242}
5243
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005244void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005245{
5246 struct mgmt_ev_new_long_term_key ev;
5247
5248 memset(&ev, 0, sizeof(ev));
5249
Marcel Holtmann5192d302014-02-19 17:11:58 -08005250 /* Devices using resolvable or non-resolvable random addresses
5251 * without providing an indentity resolving key don't require
5252 * to store long term keys. Their addresses will change the
5253 * next time around.
5254 *
5255 * Only when a remote device provides an identity address
5256 * make sure the long term key is stored. If the remote
5257 * identity is known, the long term keys are internally
5258 * mapped to the identity address. So allow static random
5259 * and public addresses here.
5260 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005261 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5262 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5263 ev.store_hint = 0x00;
5264 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005265 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005266
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005267 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005268 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005269 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005270 ev.key.enc_size = key->enc_size;
5271 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005272 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005273
5274 if (key->type == HCI_SMP_LTK)
5275 ev.key.master = 1;
5276
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005277 memcpy(ev.key.val, key->val, sizeof(key->val));
5278
Marcel Holtmann083368f2013-10-15 14:26:29 -07005279 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005280}
5281
Johan Hedberg95fbac82014-02-19 15:18:31 +02005282void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5283{
5284 struct mgmt_ev_new_irk ev;
5285
5286 memset(&ev, 0, sizeof(ev));
5287
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005288 /* For identity resolving keys from devices that are already
5289 * using a public address or static random address, do not
5290 * ask for storing this key. The identity resolving key really
5291 * is only mandatory for devices using resovlable random
5292 * addresses.
5293 *
5294 * Storing all identity resolving keys has the downside that
5295 * they will be also loaded on next boot of they system. More
5296 * identity resolving keys, means more time during scanning is
5297 * needed to actually resolve these addresses.
5298 */
5299 if (bacmp(&irk->rpa, BDADDR_ANY))
5300 ev.store_hint = 0x01;
5301 else
5302 ev.store_hint = 0x00;
5303
Johan Hedberg95fbac82014-02-19 15:18:31 +02005304 bacpy(&ev.rpa, &irk->rpa);
5305 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5306 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5307 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5308
5309 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5310}
5311
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005312void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5313 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005314{
5315 struct mgmt_ev_new_csrk ev;
5316
5317 memset(&ev, 0, sizeof(ev));
5318
5319 /* Devices using resolvable or non-resolvable random addresses
5320 * without providing an indentity resolving key don't require
5321 * to store signature resolving keys. Their addresses will change
5322 * the next time around.
5323 *
5324 * Only when a remote device provides an identity address
5325 * make sure the signature resolving key is stored. So allow
5326 * static random and public addresses here.
5327 */
5328 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5329 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5330 ev.store_hint = 0x00;
5331 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005332 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005333
5334 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5335 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5336 ev.key.master = csrk->master;
5337 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5338
5339 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5340}
5341
Marcel Holtmann94933992013-10-15 10:26:39 -07005342static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5343 u8 data_len)
5344{
5345 eir[eir_len++] = sizeof(type) + data_len;
5346 eir[eir_len++] = type;
5347 memcpy(&eir[eir_len], data, data_len);
5348 eir_len += data_len;
5349
5350 return eir_len;
5351}
5352
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005353void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5354 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5355 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005356{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005357 char buf[512];
5358 struct mgmt_ev_device_connected *ev = (void *) buf;
5359 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005360
Johan Hedbergb644ba32012-01-17 21:48:47 +02005361 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005362 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005363
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005364 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005365
Johan Hedbergb644ba32012-01-17 21:48:47 +02005366 if (name_len > 0)
5367 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005368 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005369
5370 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005371 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005372 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005373
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005374 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005375
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005376 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5377 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005378}
5379
Johan Hedberg8962ee72011-01-20 12:40:27 +02005380static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5381{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005382 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005383 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005384 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005385
Johan Hedberg88c3df12012-02-09 14:27:38 +02005386 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5387 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005388
Johan Hedbergaee9b212012-02-18 15:07:59 +02005389 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005390 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005391
5392 *sk = cmd->sk;
5393 sock_hold(*sk);
5394
Johan Hedberga664b5b2011-02-19 12:06:02 -03005395 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005396}
5397
Johan Hedberg124f6e32012-02-09 13:50:12 +02005398static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005399{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005400 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005401 struct mgmt_cp_unpair_device *cp = cmd->param;
5402 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005403
5404 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005405 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5406 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005407
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005408 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5409
Johan Hedbergaee9b212012-02-18 15:07:59 +02005410 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005411
5412 mgmt_pending_remove(cmd);
5413}
5414
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005415void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005416 u8 link_type, u8 addr_type, u8 reason,
5417 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005418{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005419 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005420 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005421 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005422
Johan Hedberg8b064a32014-02-24 14:52:22 +02005423 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5424 if (power_off) {
5425 struct mgmt_mode *cp = power_off->param;
5426
5427 /* The connection is still in hci_conn_hash so test for 1
5428 * instead of 0 to know if this is the last one.
5429 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005430 if (!cp->val && hci_conn_count(hdev) == 1) {
5431 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005432 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005433 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005434 }
5435
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005436 if (!mgmt_connected)
5437 return;
5438
Andre Guedes57eb7762013-10-30 19:01:41 -03005439 if (link_type != ACL_LINK && link_type != LE_LINK)
5440 return;
5441
Johan Hedberg744cf192011-11-08 20:40:14 +02005442 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005443
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005444 bacpy(&ev.addr.bdaddr, bdaddr);
5445 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5446 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005447
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005448 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005449
5450 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005451 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005452
Johan Hedberg124f6e32012-02-09 13:50:12 +02005453 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005454 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005455}
5456
Marcel Holtmann78929242013-10-06 23:55:47 -07005457void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5458 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005459{
Andre Guedes3655bba2013-10-30 19:01:40 -03005460 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5461 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005462 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005463 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005464
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005465 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5466 hdev);
5467
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005468 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005469 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005470 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005471
Andre Guedes3655bba2013-10-30 19:01:40 -03005472 cp = cmd->param;
5473
5474 if (bacmp(bdaddr, &cp->addr.bdaddr))
5475 return;
5476
5477 if (cp->addr.type != bdaddr_type)
5478 return;
5479
Johan Hedberg88c3df12012-02-09 14:27:38 +02005480 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005481 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005482
Marcel Holtmann78929242013-10-06 23:55:47 -07005483 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5484 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005485
Johan Hedberga664b5b2011-02-19 12:06:02 -03005486 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005487}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005488
Marcel Holtmann445608d2013-10-06 23:55:48 -07005489void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5490 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005491{
5492 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005493 struct pending_cmd *power_off;
5494
5495 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5496 if (power_off) {
5497 struct mgmt_mode *cp = power_off->param;
5498
5499 /* The connection is still in hci_conn_hash so test for 1
5500 * instead of 0 to know if this is the last one.
5501 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005502 if (!cp->val && hci_conn_count(hdev) == 1) {
5503 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005504 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005505 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005506 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005507
Johan Hedberg4c659c32011-11-07 23:13:39 +02005508 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005509 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005510 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005511
Marcel Holtmann445608d2013-10-06 23:55:48 -07005512 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005513}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005514
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005515void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005516{
5517 struct mgmt_ev_pin_code_request ev;
5518
Johan Hedbergd8457692012-02-17 14:24:57 +02005519 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005520 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005521 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005522
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005523 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005524}
5525
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005526void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5527 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005528{
5529 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005530 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005531
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005532 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005533 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005534 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005535
Johan Hedbergd8457692012-02-17 14:24:57 +02005536 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005537 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005538
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005539 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5540 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005541
Johan Hedberga664b5b2011-02-19 12:06:02 -03005542 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005543}
5544
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005545void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5546 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005547{
5548 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005549 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005550
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005551 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005552 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005553 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005554
Johan Hedbergd8457692012-02-17 14:24:57 +02005555 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005556 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005557
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005558 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5559 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005560
Johan Hedberga664b5b2011-02-19 12:06:02 -03005561 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005562}
Johan Hedberga5c29682011-02-19 12:05:57 -03005563
Johan Hedberg744cf192011-11-08 20:40:14 +02005564int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005565 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005566 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005567{
5568 struct mgmt_ev_user_confirm_request ev;
5569
Johan Hedberg744cf192011-11-08 20:40:14 +02005570 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005571
Johan Hedberg272d90d2012-02-09 15:26:12 +02005572 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005573 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005574 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005575 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005576
Johan Hedberg744cf192011-11-08 20:40:14 +02005577 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005578 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005579}
5580
Johan Hedberg272d90d2012-02-09 15:26:12 +02005581int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005582 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005583{
5584 struct mgmt_ev_user_passkey_request ev;
5585
5586 BT_DBG("%s", hdev->name);
5587
Johan Hedberg272d90d2012-02-09 15:26:12 +02005588 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005589 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005590
5591 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005592 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005593}
5594
Brian Gix0df4c182011-11-16 13:53:13 -08005595static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005596 u8 link_type, u8 addr_type, u8 status,
5597 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005598{
5599 struct pending_cmd *cmd;
5600 struct mgmt_rp_user_confirm_reply rp;
5601 int err;
5602
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005603 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005604 if (!cmd)
5605 return -ENOENT;
5606
Johan Hedberg272d90d2012-02-09 15:26:12 +02005607 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005608 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005609 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005610 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005611
Johan Hedberga664b5b2011-02-19 12:06:02 -03005612 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005613
5614 return err;
5615}
5616
Johan Hedberg744cf192011-11-08 20:40:14 +02005617int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005618 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005619{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005620 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005621 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005622}
5623
Johan Hedberg272d90d2012-02-09 15:26:12 +02005624int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005625 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005626{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005627 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005628 status,
5629 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005630}
Johan Hedberg2a611692011-02-19 12:06:00 -03005631
Brian Gix604086b2011-11-23 08:28:33 -08005632int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005633 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005634{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005635 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005636 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005637}
5638
Johan Hedberg272d90d2012-02-09 15:26:12 +02005639int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005640 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005641{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005642 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005643 status,
5644 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005645}
5646
Johan Hedberg92a25252012-09-06 18:39:26 +03005647int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5648 u8 link_type, u8 addr_type, u32 passkey,
5649 u8 entered)
5650{
5651 struct mgmt_ev_passkey_notify ev;
5652
5653 BT_DBG("%s", hdev->name);
5654
5655 bacpy(&ev.addr.bdaddr, bdaddr);
5656 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5657 ev.passkey = __cpu_to_le32(passkey);
5658 ev.entered = entered;
5659
5660 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5661}
5662
Marcel Holtmanne5460992013-10-15 14:26:23 -07005663void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5664 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005665{
5666 struct mgmt_ev_auth_failed ev;
5667
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005668 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005669 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005670 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005671
Marcel Holtmanne5460992013-10-15 14:26:23 -07005672 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005673}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005674
Marcel Holtmann464996a2013-10-15 14:26:24 -07005675void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005676{
5677 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005678 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005679
5680 if (status) {
5681 u8 mgmt_err = mgmt_status(status);
5682 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005683 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005684 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005685 }
5686
Marcel Holtmann464996a2013-10-15 14:26:24 -07005687 if (test_bit(HCI_AUTH, &hdev->flags))
5688 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5689 &hdev->dev_flags);
5690 else
5691 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5692 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005693
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005694 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005695 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005696
Johan Hedberg47990ea2012-02-22 11:58:37 +02005697 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005698 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005699
5700 if (match.sk)
5701 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005702}
5703
Johan Hedberg890ea892013-03-15 17:06:52 -05005704static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005705{
Johan Hedberg890ea892013-03-15 17:06:52 -05005706 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005707 struct hci_cp_write_eir cp;
5708
Johan Hedberg976eb202012-10-24 21:12:01 +03005709 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005710 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005711
Johan Hedbergc80da272012-02-22 15:38:48 +02005712 memset(hdev->eir, 0, sizeof(hdev->eir));
5713
Johan Hedbergcacaf522012-02-21 00:52:42 +02005714 memset(&cp, 0, sizeof(cp));
5715
Johan Hedberg890ea892013-03-15 17:06:52 -05005716 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005717}
5718
Marcel Holtmann3e248562013-10-15 14:26:25 -07005719void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005720{
5721 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005722 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005723 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005724
5725 if (status) {
5726 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005727
5728 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005729 &hdev->dev_flags)) {
5730 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005731 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005732 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005733
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005734 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5735 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005736 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005737 }
5738
5739 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005740 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005741 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005742 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5743 if (!changed)
5744 changed = test_and_clear_bit(HCI_HS_ENABLED,
5745 &hdev->dev_flags);
5746 else
5747 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005748 }
5749
5750 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5751
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005752 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005753 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005754
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005755 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005756 sock_put(match.sk);
5757
Johan Hedberg890ea892013-03-15 17:06:52 -05005758 hci_req_init(&req, hdev);
5759
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005760 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005761 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005762 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005763 clear_eir(&req);
5764
5765 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005766}
5767
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005768void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5769{
5770 struct cmd_lookup match = { NULL, hdev };
5771 bool changed = false;
5772
5773 if (status) {
5774 u8 mgmt_err = mgmt_status(status);
5775
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005776 if (enable) {
5777 if (test_and_clear_bit(HCI_SC_ENABLED,
5778 &hdev->dev_flags))
5779 new_settings(hdev, NULL);
5780 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5781 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005782
5783 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5784 cmd_status_rsp, &mgmt_err);
5785 return;
5786 }
5787
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005788 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005789 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005790 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005791 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005792 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5793 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005794
5795 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5796 settings_rsp, &match);
5797
5798 if (changed)
5799 new_settings(hdev, match.sk);
5800
5801 if (match.sk)
5802 sock_put(match.sk);
5803}
5804
Johan Hedberg92da6092013-03-15 17:06:55 -05005805static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005806{
5807 struct cmd_lookup *match = data;
5808
Johan Hedberg90e70452012-02-23 23:09:40 +02005809 if (match->sk == NULL) {
5810 match->sk = cmd->sk;
5811 sock_hold(match->sk);
5812 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005813}
5814
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005815void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5816 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005817{
Johan Hedberg90e70452012-02-23 23:09:40 +02005818 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005819
Johan Hedberg92da6092013-03-15 17:06:55 -05005820 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5821 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5822 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005823
5824 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005825 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5826 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005827
5828 if (match.sk)
5829 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005830}
5831
Marcel Holtmann7667da32013-10-15 14:26:27 -07005832void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005833{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005834 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005835 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005836
Johan Hedberg13928972013-03-15 17:07:00 -05005837 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005838 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005839
5840 memset(&ev, 0, sizeof(ev));
5841 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005842 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005843
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005844 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005845 if (!cmd) {
5846 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005847
Johan Hedberg13928972013-03-15 17:07:00 -05005848 /* If this is a HCI command related to powering on the
5849 * HCI dev don't send any mgmt signals.
5850 */
5851 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005852 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005853 }
5854
Marcel Holtmann7667da32013-10-15 14:26:27 -07005855 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5856 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005857}
Szymon Jancc35938b2011-03-22 13:12:21 +01005858
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005859void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5860 u8 *randomizer192, u8 *hash256,
5861 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005862{
5863 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005864
Johan Hedberg744cf192011-11-08 20:40:14 +02005865 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005866
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005867 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005868 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005869 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005870
5871 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005872 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5873 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005874 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005875 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5876 hash256 && randomizer256) {
5877 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005878
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005879 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5880 memcpy(rp.randomizer192, randomizer192,
5881 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005882
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005883 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5884 memcpy(rp.randomizer256, randomizer256,
5885 sizeof(rp.randomizer256));
5886
5887 cmd_complete(cmd->sk, hdev->id,
5888 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5889 &rp, sizeof(rp));
5890 } else {
5891 struct mgmt_rp_read_local_oob_data rp;
5892
5893 memcpy(rp.hash, hash192, sizeof(rp.hash));
5894 memcpy(rp.randomizer, randomizer192,
5895 sizeof(rp.randomizer));
5896
5897 cmd_complete(cmd->sk, hdev->id,
5898 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5899 &rp, sizeof(rp));
5900 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005901 }
5902
5903 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005904}
Johan Hedberge17acd42011-03-30 23:57:16 +03005905
Marcel Holtmann901801b2013-10-06 23:55:51 -07005906void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02005907 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
5908 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005909 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005910{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005911 char buf[512];
5912 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005913 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005914 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005915
Andre Guedes12602d02013-04-30 15:29:40 -03005916 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005917 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005918
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005919 /* Make sure that the buffer is big enough. The 5 extra bytes
5920 * are for the potential CoD field.
5921 */
5922 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005923 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005924
Johan Hedberg1dc06092012-01-15 21:01:23 +02005925 memset(buf, 0, sizeof(buf));
5926
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005927 irk = hci_get_irk(hdev, bdaddr, addr_type);
5928 if (irk) {
5929 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5930 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5931 } else {
5932 bacpy(&ev->addr.bdaddr, bdaddr);
5933 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5934 }
5935
Johan Hedberge319d2e2012-01-15 19:51:59 +02005936 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005937 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005938 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005939 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005940 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005941
Johan Hedberg1dc06092012-01-15 21:01:23 +02005942 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005943 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005944
Johan Hedberg1dc06092012-01-15 21:01:23 +02005945 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5946 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005947 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005948
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005949 if (scan_rsp_len > 0)
5950 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
5951
5952 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
5953 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005954
Marcel Holtmann901801b2013-10-06 23:55:51 -07005955 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005956}
Johan Hedberga88a9652011-03-30 13:18:12 +03005957
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005958void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5959 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005960{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005961 struct mgmt_ev_device_found *ev;
5962 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5963 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005964
Johan Hedbergb644ba32012-01-17 21:48:47 +02005965 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005966
Johan Hedbergb644ba32012-01-17 21:48:47 +02005967 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005968
Johan Hedbergb644ba32012-01-17 21:48:47 +02005969 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005970 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005971 ev->rssi = rssi;
5972
5973 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005974 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005975
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005976 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005977
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005978 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005979}
Johan Hedberg314b2382011-04-27 10:29:57 -04005980
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005981void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005982{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005983 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005984 struct pending_cmd *cmd;
5985
Andre Guedes343fb142011-11-22 17:14:19 -03005986 BT_DBG("%s discovering %u", hdev->name, discovering);
5987
Johan Hedberg164a6e72011-11-01 17:06:44 +02005988 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005989 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005990 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005991 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005992
5993 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005994 u8 type = hdev->discovery.type;
5995
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005996 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5997 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005998 mgmt_pending_remove(cmd);
5999 }
6000
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006001 memset(&ev, 0, sizeof(ev));
6002 ev.type = hdev->discovery.type;
6003 ev.discovering = discovering;
6004
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006005 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006006}
Antti Julku5e762442011-08-25 16:48:02 +03006007
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006008int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006009{
6010 struct pending_cmd *cmd;
6011 struct mgmt_ev_device_blocked ev;
6012
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006013 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006014
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006015 bacpy(&ev.addr.bdaddr, bdaddr);
6016 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006017
Johan Hedberg744cf192011-11-08 20:40:14 +02006018 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006019 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006020}
6021
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006022int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006023{
6024 struct pending_cmd *cmd;
6025 struct mgmt_ev_device_unblocked ev;
6026
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006027 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006028
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006029 bacpy(&ev.addr.bdaddr, bdaddr);
6030 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006031
Johan Hedberg744cf192011-11-08 20:40:14 +02006032 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006033 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006034}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006035
6036static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6037{
6038 BT_DBG("%s status %u", hdev->name, status);
6039
6040 /* Clear the advertising mgmt setting if we failed to re-enable it */
6041 if (status) {
6042 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006043 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006044 }
6045}
6046
6047void mgmt_reenable_advertising(struct hci_dev *hdev)
6048{
6049 struct hci_request req;
6050
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006051 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006052 return;
6053
6054 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6055 return;
6056
6057 hci_req_init(&req, hdev);
6058 enable_advertising(&req);
6059
6060 /* If this fails we have no option but to let user space know
6061 * that we've disabled advertising.
6062 */
6063 if (hci_req_run(&req, adv_enable_complete) < 0) {
6064 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006065 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006066 }
6067}