blob: 634b44ddc9f9f313527e10832e5090d490fcbcf1 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmannb75cf9c2014-05-09 04:18:42 -070038#define MGMT_REVISION 6
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020088};
89
90static const u16 mgmt_events[] = {
91 MGMT_EV_CONTROLLER_ERROR,
92 MGMT_EV_INDEX_ADDED,
93 MGMT_EV_INDEX_REMOVED,
94 MGMT_EV_NEW_SETTINGS,
95 MGMT_EV_CLASS_OF_DEV_CHANGED,
96 MGMT_EV_LOCAL_NAME_CHANGED,
97 MGMT_EV_NEW_LINK_KEY,
98 MGMT_EV_NEW_LONG_TERM_KEY,
99 MGMT_EV_DEVICE_CONNECTED,
100 MGMT_EV_DEVICE_DISCONNECTED,
101 MGMT_EV_CONNECT_FAILED,
102 MGMT_EV_PIN_CODE_REQUEST,
103 MGMT_EV_USER_CONFIRM_REQUEST,
104 MGMT_EV_USER_PASSKEY_REQUEST,
105 MGMT_EV_AUTH_FAILED,
106 MGMT_EV_DEVICE_FOUND,
107 MGMT_EV_DISCOVERING,
108 MGMT_EV_DEVICE_BLOCKED,
109 MGMT_EV_DEVICE_UNBLOCKED,
110 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300111 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800112 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700113 MGMT_EV_NEW_CSRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200114};
115
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800116#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200117
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200118#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
119 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
120
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200121struct pending_cmd {
122 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200123 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200124 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100125 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200126 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300127 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200128};
129
Johan Hedbergca69b792011-11-11 18:10:00 +0200130/* HCI to MGMT error code conversion table */
131static u8 mgmt_status_table[] = {
132 MGMT_STATUS_SUCCESS,
133 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
134 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
135 MGMT_STATUS_FAILED, /* Hardware Failure */
136 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
137 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200138 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200139 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
140 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
141 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
142 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
143 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
144 MGMT_STATUS_BUSY, /* Command Disallowed */
145 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
146 MGMT_STATUS_REJECTED, /* Rejected Security */
147 MGMT_STATUS_REJECTED, /* Rejected Personal */
148 MGMT_STATUS_TIMEOUT, /* Host Timeout */
149 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
150 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
151 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
152 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
153 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
154 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
155 MGMT_STATUS_BUSY, /* Repeated Attempts */
156 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
157 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
158 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
159 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
160 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
161 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
162 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
163 MGMT_STATUS_FAILED, /* Unspecified Error */
164 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
165 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
166 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
167 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
168 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
169 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
170 MGMT_STATUS_FAILED, /* Unit Link Key Used */
171 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
172 MGMT_STATUS_TIMEOUT, /* Instant Passed */
173 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
174 MGMT_STATUS_FAILED, /* Transaction Collision */
175 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
176 MGMT_STATUS_REJECTED, /* QoS Rejected */
177 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
178 MGMT_STATUS_REJECTED, /* Insufficient Security */
179 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
180 MGMT_STATUS_BUSY, /* Role Switch Pending */
181 MGMT_STATUS_FAILED, /* Slot Violation */
182 MGMT_STATUS_FAILED, /* Role Switch Failed */
183 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
184 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
185 MGMT_STATUS_BUSY, /* Host Busy Pairing */
186 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
187 MGMT_STATUS_BUSY, /* Controller Busy */
188 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
189 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
190 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
191 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
192 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
193};
194
195static u8 mgmt_status(u8 hci_status)
196{
197 if (hci_status < ARRAY_SIZE(mgmt_status_table))
198 return mgmt_status_table[hci_status];
199
200 return MGMT_STATUS_FAILED;
201}
202
Szymon Janc4e51eae2011-02-25 19:05:48 +0100203static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200204{
205 struct sk_buff *skb;
206 struct mgmt_hdr *hdr;
207 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300208 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200209
Szymon Janc34eb5252011-02-28 14:10:08 +0100210 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200211
Andre Guedes790eff42012-06-07 19:05:46 -0300212 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200213 if (!skb)
214 return -ENOMEM;
215
216 hdr = (void *) skb_put(skb, sizeof(*hdr));
217
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700218 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100219 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200220 hdr->len = cpu_to_le16(sizeof(*ev));
221
222 ev = (void *) skb_put(skb, sizeof(*ev));
223 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200224 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200225
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300226 err = sock_queue_rcv_skb(sk, skb);
227 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200228 kfree_skb(skb);
229
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300230 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200231}
232
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200233static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300234 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200235{
236 struct sk_buff *skb;
237 struct mgmt_hdr *hdr;
238 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300239 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200240
241 BT_DBG("sock %p", sk);
242
Andre Guedes790eff42012-06-07 19:05:46 -0300243 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200244 if (!skb)
245 return -ENOMEM;
246
247 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200248
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700249 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100250 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200251 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200252
Johan Hedberga38528f2011-01-22 06:46:43 +0200253 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200254 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200255 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100256
257 if (rp)
258 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200259
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300260 err = sock_queue_rcv_skb(sk, skb);
261 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200262 kfree_skb(skb);
263
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100264 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200265}
266
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300267static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
268 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200269{
270 struct mgmt_rp_read_version rp;
271
272 BT_DBG("sock %p", sk);
273
274 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200279}
280
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300281static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
282 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200283{
284 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200285 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
286 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200287 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200288 size_t rp_size;
289 int i, err;
290
291 BT_DBG("sock %p", sk);
292
293 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
294
295 rp = kmalloc(rp_size, GFP_KERNEL);
296 if (!rp)
297 return -ENOMEM;
298
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700299 rp->num_commands = cpu_to_le16(num_commands);
300 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200301
302 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
303 put_unaligned_le16(mgmt_commands[i], opcode);
304
305 for (i = 0; i < num_events; i++, opcode++)
306 put_unaligned_le16(mgmt_events[i], opcode);
307
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200308 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300309 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200310 kfree(rp);
311
312 return err;
313}
314
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300315static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
316 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200317{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200318 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200319 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200320 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200321 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300322 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200323
324 BT_DBG("sock %p", sk);
325
326 read_lock(&hci_dev_list_lock);
327
328 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300329 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700330 if (d->dev_type == HCI_BREDR)
331 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200332 }
333
Johan Hedberga38528f2011-01-22 06:46:43 +0200334 rp_len = sizeof(*rp) + (2 * count);
335 rp = kmalloc(rp_len, GFP_ATOMIC);
336 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100337 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200338 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100339 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340
Johan Hedberg476e44c2012-10-19 20:10:46 +0300341 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200342 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200343 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200344 continue;
345
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700346 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
347 continue;
348
Marcel Holtmann1514b892013-10-06 08:25:01 -0700349 if (d->dev_type == HCI_BREDR) {
350 rp->index[count++] = cpu_to_le16(d->id);
351 BT_DBG("Added hci%u", d->id);
352 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200353 }
354
Johan Hedberg476e44c2012-10-19 20:10:46 +0300355 rp->num_controllers = cpu_to_le16(count);
356 rp_len = sizeof(*rp) + (2 * count);
357
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200358 read_unlock(&hci_dev_list_lock);
359
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200360 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300361 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362
Johan Hedberga38528f2011-01-22 06:46:43 +0200363 kfree(rp);
364
365 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366}
367
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200368static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200369{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200370 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200371
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200372 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200373 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800374 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200375
Andre Guedesed3fa312012-07-24 15:03:46 -0300376 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300377 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500378 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
379 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300380 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200381 settings |= MGMT_SETTING_BREDR;
382 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700383
384 if (lmp_ssp_capable(hdev)) {
385 settings |= MGMT_SETTING_SSP;
386 settings |= MGMT_SETTING_HS;
387 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800388
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800389 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200390 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800391 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700392 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100393
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300394 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200395 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300396 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200397 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300398 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200399
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200400 return settings;
401}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200402
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200403static u32 get_current_settings(struct hci_dev *hdev)
404{
405 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200406
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200407 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100408 settings |= MGMT_SETTING_POWERED;
409
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200410 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200411 settings |= MGMT_SETTING_CONNECTABLE;
412
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500413 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
414 settings |= MGMT_SETTING_FAST_CONNECTABLE;
415
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200416 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200417 settings |= MGMT_SETTING_DISCOVERABLE;
418
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200419 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200420 settings |= MGMT_SETTING_PAIRABLE;
421
Johan Hedberg56f87902013-10-02 13:43:13 +0300422 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200423 settings |= MGMT_SETTING_BREDR;
424
Johan Hedberg06199cf2012-02-22 16:37:11 +0200425 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200426 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200427
Johan Hedberg47990ea2012-02-22 11:58:37 +0200428 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200430
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200431 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200432 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200433
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200434 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
435 settings |= MGMT_SETTING_HS;
436
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200437 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300438 settings |= MGMT_SETTING_ADVERTISING;
439
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800440 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
441 settings |= MGMT_SETTING_SECURE_CONN;
442
Johan Hedberg0663b292014-06-24 13:15:50 +0300443 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800444 settings |= MGMT_SETTING_DEBUG_KEYS;
445
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200446 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
447 settings |= MGMT_SETTING_PRIVACY;
448
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200449 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200450}
451
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300452#define PNP_INFO_SVCLASS_ID 0x1200
453
Johan Hedberg213202e2013-01-27 00:31:33 +0200454static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
455{
456 u8 *ptr = data, *uuids_start = NULL;
457 struct bt_uuid *uuid;
458
459 if (len < 4)
460 return ptr;
461
462 list_for_each_entry(uuid, &hdev->uuids, list) {
463 u16 uuid16;
464
465 if (uuid->size != 16)
466 continue;
467
468 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
469 if (uuid16 < 0x1100)
470 continue;
471
472 if (uuid16 == PNP_INFO_SVCLASS_ID)
473 continue;
474
475 if (!uuids_start) {
476 uuids_start = ptr;
477 uuids_start[0] = 1;
478 uuids_start[1] = EIR_UUID16_ALL;
479 ptr += 2;
480 }
481
482 /* Stop if not enough space to put next UUID */
483 if ((ptr - data) + sizeof(u16) > len) {
484 uuids_start[1] = EIR_UUID16_SOME;
485 break;
486 }
487
488 *ptr++ = (uuid16 & 0x00ff);
489 *ptr++ = (uuid16 & 0xff00) >> 8;
490 uuids_start[0] += sizeof(uuid16);
491 }
492
493 return ptr;
494}
495
Johan Hedbergcdf19632013-01-27 00:31:34 +0200496static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
497{
498 u8 *ptr = data, *uuids_start = NULL;
499 struct bt_uuid *uuid;
500
501 if (len < 6)
502 return ptr;
503
504 list_for_each_entry(uuid, &hdev->uuids, list) {
505 if (uuid->size != 32)
506 continue;
507
508 if (!uuids_start) {
509 uuids_start = ptr;
510 uuids_start[0] = 1;
511 uuids_start[1] = EIR_UUID32_ALL;
512 ptr += 2;
513 }
514
515 /* Stop if not enough space to put next UUID */
516 if ((ptr - data) + sizeof(u32) > len) {
517 uuids_start[1] = EIR_UUID32_SOME;
518 break;
519 }
520
521 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
522 ptr += sizeof(u32);
523 uuids_start[0] += sizeof(u32);
524 }
525
526 return ptr;
527}
528
Johan Hedbergc00d5752013-01-27 00:31:35 +0200529static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
530{
531 u8 *ptr = data, *uuids_start = NULL;
532 struct bt_uuid *uuid;
533
534 if (len < 18)
535 return ptr;
536
537 list_for_each_entry(uuid, &hdev->uuids, list) {
538 if (uuid->size != 128)
539 continue;
540
541 if (!uuids_start) {
542 uuids_start = ptr;
543 uuids_start[0] = 1;
544 uuids_start[1] = EIR_UUID128_ALL;
545 ptr += 2;
546 }
547
548 /* Stop if not enough space to put next UUID */
549 if ((ptr - data) + 16 > len) {
550 uuids_start[1] = EIR_UUID128_SOME;
551 break;
552 }
553
554 memcpy(ptr, uuid->uuid, 16);
555 ptr += 16;
556 uuids_start[0] += 16;
557 }
558
559 return ptr;
560}
561
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300562static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
563{
564 struct pending_cmd *cmd;
565
566 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
567 if (cmd->opcode == opcode)
568 return cmd;
569 }
570
571 return NULL;
572}
573
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700574static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
575{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700576 u8 ad_len = 0;
577 size_t name_len;
578
579 name_len = strlen(hdev->dev_name);
580 if (name_len > 0) {
581 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
582
583 if (name_len > max_len) {
584 name_len = max_len;
585 ptr[1] = EIR_NAME_SHORT;
586 } else
587 ptr[1] = EIR_NAME_COMPLETE;
588
589 ptr[0] = name_len + 1;
590
591 memcpy(ptr + 2, hdev->dev_name, name_len);
592
593 ad_len += (name_len + 2);
594 ptr += (name_len + 2);
595 }
596
597 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700598}
599
600static void update_scan_rsp_data(struct hci_request *req)
601{
602 struct hci_dev *hdev = req->hdev;
603 struct hci_cp_le_set_scan_rsp_data cp;
604 u8 len;
605
Johan Hedberg7751ef12013-10-19 23:38:15 +0300606 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700607 return;
608
609 memset(&cp, 0, sizeof(cp));
610
611 len = create_scan_rsp_data(hdev, cp.data);
612
Johan Hedbergeb438b52013-10-16 15:31:07 +0300613 if (hdev->scan_rsp_data_len == len &&
614 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700615 return;
616
Johan Hedbergeb438b52013-10-16 15:31:07 +0300617 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
618 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700619
620 cp.length = len;
621
622 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
623}
624
Johan Hedberg9a43e252013-10-20 19:00:07 +0300625static u8 get_adv_discov_flags(struct hci_dev *hdev)
626{
627 struct pending_cmd *cmd;
628
629 /* If there's a pending mgmt command the flags will not yet have
630 * their final values, so check for this first.
631 */
632 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
633 if (cmd) {
634 struct mgmt_mode *cp = cmd->param;
635 if (cp->val == 0x01)
636 return LE_AD_GENERAL;
637 else if (cp->val == 0x02)
638 return LE_AD_LIMITED;
639 } else {
640 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
641 return LE_AD_LIMITED;
642 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
643 return LE_AD_GENERAL;
644 }
645
646 return 0;
647}
648
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700649static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700650{
651 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700652
Johan Hedberg9a43e252013-10-20 19:00:07 +0300653 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700654
Johan Hedberge8340042014-01-30 11:16:50 -0800655 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700656 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700657
658 if (flags) {
659 BT_DBG("adv flags 0x%02x", flags);
660
661 ptr[0] = 2;
662 ptr[1] = EIR_FLAGS;
663 ptr[2] = flags;
664
665 ad_len += 3;
666 ptr += 3;
667 }
668
669 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
670 ptr[0] = 2;
671 ptr[1] = EIR_TX_POWER;
672 ptr[2] = (u8) hdev->adv_tx_power;
673
674 ad_len += 3;
675 ptr += 3;
676 }
677
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678 return ad_len;
679}
680
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700681static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700682{
683 struct hci_dev *hdev = req->hdev;
684 struct hci_cp_le_set_adv_data cp;
685 u8 len;
686
Johan Hedberg10994ce2013-10-19 23:38:16 +0300687 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700688 return;
689
690 memset(&cp, 0, sizeof(cp));
691
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700692 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700693
694 if (hdev->adv_data_len == len &&
695 memcmp(cp.data, hdev->adv_data, len) == 0)
696 return;
697
698 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
699 hdev->adv_data_len = len;
700
701 cp.length = len;
702
703 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
704}
705
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300706static void create_eir(struct hci_dev *hdev, u8 *data)
707{
708 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300709 size_t name_len;
710
711 name_len = strlen(hdev->dev_name);
712
713 if (name_len > 0) {
714 /* EIR Data type */
715 if (name_len > 48) {
716 name_len = 48;
717 ptr[1] = EIR_NAME_SHORT;
718 } else
719 ptr[1] = EIR_NAME_COMPLETE;
720
721 /* EIR Data length */
722 ptr[0] = name_len + 1;
723
724 memcpy(ptr + 2, hdev->dev_name, name_len);
725
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300726 ptr += (name_len + 2);
727 }
728
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100729 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700730 ptr[0] = 2;
731 ptr[1] = EIR_TX_POWER;
732 ptr[2] = (u8) hdev->inq_tx_power;
733
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700734 ptr += 3;
735 }
736
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700737 if (hdev->devid_source > 0) {
738 ptr[0] = 9;
739 ptr[1] = EIR_DEVICE_ID;
740
741 put_unaligned_le16(hdev->devid_source, ptr + 2);
742 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
743 put_unaligned_le16(hdev->devid_product, ptr + 6);
744 put_unaligned_le16(hdev->devid_version, ptr + 8);
745
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700746 ptr += 10;
747 }
748
Johan Hedberg213202e2013-01-27 00:31:33 +0200749 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200750 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200751 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300752}
753
Johan Hedberg890ea892013-03-15 17:06:52 -0500754static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300755{
Johan Hedberg890ea892013-03-15 17:06:52 -0500756 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300757 struct hci_cp_write_eir cp;
758
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200759 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500760 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200761
Johan Hedberg976eb202012-10-24 21:12:01 +0300762 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500763 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300764
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200765 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500766 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300767
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200768 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500769 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300770
771 memset(&cp, 0, sizeof(cp));
772
773 create_eir(hdev, cp.data);
774
775 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500776 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300777
778 memcpy(hdev->eir, cp.data, sizeof(cp.data));
779
Johan Hedberg890ea892013-03-15 17:06:52 -0500780 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300781}
782
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200783static u8 get_service_classes(struct hci_dev *hdev)
784{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300785 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200786 u8 val = 0;
787
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300788 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200789 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200790
791 return val;
792}
793
Johan Hedberg890ea892013-03-15 17:06:52 -0500794static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200795{
Johan Hedberg890ea892013-03-15 17:06:52 -0500796 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200797 u8 cod[3];
798
799 BT_DBG("%s", hdev->name);
800
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200801 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500802 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200803
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300804 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
805 return;
806
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200807 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500808 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200809
810 cod[0] = hdev->minor_class;
811 cod[1] = hdev->major_class;
812 cod[2] = get_service_classes(hdev);
813
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700814 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
815 cod[1] |= 0x20;
816
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500818 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200819
Johan Hedberg890ea892013-03-15 17:06:52 -0500820 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200821}
822
Johan Hedberga4858cb2014-02-25 19:56:31 +0200823static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200824{
825 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200826
827 /* If there's a pending mgmt command the flag will not yet have
828 * it's final value, so check for this first.
829 */
830 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
831 if (cmd) {
832 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200833 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200834 }
835
Johan Hedberga4858cb2014-02-25 19:56:31 +0200836 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200837}
838
839static void enable_advertising(struct hci_request *req)
840{
841 struct hci_dev *hdev = req->hdev;
842 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200843 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200844 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200845
Johan Hedberg8d972502014-02-28 12:54:14 +0200846 /* Clear the HCI_ADVERTISING bit temporarily so that the
847 * hci_update_random_address knows that it's safe to go ahead
848 * and write a new random address. The flag will be set back on
849 * as soon as the SET_ADV_ENABLE HCI command completes.
850 */
851 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
852
Johan Hedberga4858cb2014-02-25 19:56:31 +0200853 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200854
Johan Hedberga4858cb2014-02-25 19:56:31 +0200855 /* Set require_privacy to true only when non-connectable
856 * advertising is used. In that case it is fine to use a
857 * non-resolvable private address.
858 */
859 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200860 return;
861
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800862 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700863 cp.min_interval = cpu_to_le16(0x0800);
864 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200865 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200866 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200867 cp.channel_map = hdev->le_adv_channel_map;
868
869 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
870
871 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
872}
873
874static void disable_advertising(struct hci_request *req)
875{
876 u8 enable = 0x00;
877
878 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
879}
880
Johan Hedberg7d785252011-12-15 00:47:39 +0200881static void service_cache_off(struct work_struct *work)
882{
883 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300884 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500885 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200886
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200887 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200888 return;
889
Johan Hedberg890ea892013-03-15 17:06:52 -0500890 hci_req_init(&req, hdev);
891
Johan Hedberg7d785252011-12-15 00:47:39 +0200892 hci_dev_lock(hdev);
893
Johan Hedberg890ea892013-03-15 17:06:52 -0500894 update_eir(&req);
895 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200896
897 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500898
899 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200900}
901
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200902static void rpa_expired(struct work_struct *work)
903{
904 struct hci_dev *hdev = container_of(work, struct hci_dev,
905 rpa_expired.work);
906 struct hci_request req;
907
908 BT_DBG("");
909
910 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
911
912 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
913 hci_conn_num(hdev, LE_LINK) > 0)
914 return;
915
916 /* The generation of a new RPA and programming it into the
917 * controller happens in the enable_advertising() function.
918 */
919
920 hci_req_init(&req, hdev);
921
922 disable_advertising(&req);
923 enable_advertising(&req);
924
925 hci_req_run(&req, NULL);
926}
927
Johan Hedberg6a919082012-02-28 06:17:26 +0200928static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200929{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200930 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200931 return;
932
Johan Hedberg4f87da82012-03-02 19:55:56 +0200933 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200934 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200935
Johan Hedberg4f87da82012-03-02 19:55:56 +0200936 /* Non-mgmt controlled devices get this bit set
937 * implicitly so that pairing works for them, however
938 * for mgmt we require user-space to explicitly enable
939 * it
940 */
941 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200942}
943
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200944static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300945 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200946{
947 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200948
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200949 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200950
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300951 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200952
Johan Hedberg03811012010-12-08 00:21:06 +0200953 memset(&rp, 0, sizeof(rp));
954
Johan Hedberg03811012010-12-08 00:21:06 +0200955 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200956
957 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200958 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200959
960 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
961 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
962
963 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200964
965 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200966 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300968 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200969
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200970 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300971 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200972}
973
974static void mgmt_pending_free(struct pending_cmd *cmd)
975{
976 sock_put(cmd->sk);
977 kfree(cmd->param);
978 kfree(cmd);
979}
980
981static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300982 struct hci_dev *hdev, void *data,
983 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200984{
985 struct pending_cmd *cmd;
986
Andre Guedes12b94562012-06-07 19:05:45 -0300987 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200988 if (!cmd)
989 return NULL;
990
991 cmd->opcode = opcode;
992 cmd->index = hdev->id;
993
Andre Guedes12b94562012-06-07 19:05:45 -0300994 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200995 if (!cmd->param) {
996 kfree(cmd);
997 return NULL;
998 }
999
1000 if (data)
1001 memcpy(cmd->param, data, len);
1002
1003 cmd->sk = sk;
1004 sock_hold(sk);
1005
1006 list_add(&cmd->list, &hdev->mgmt_pending);
1007
1008 return cmd;
1009}
1010
1011static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001012 void (*cb)(struct pending_cmd *cmd,
1013 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001014 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001015{
Andre Guedesa3d09352013-02-01 11:21:30 -03001016 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001017
Andre Guedesa3d09352013-02-01 11:21:30 -03001018 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001019 if (opcode > 0 && cmd->opcode != opcode)
1020 continue;
1021
1022 cb(cmd, data);
1023 }
1024}
1025
Johan Hedberg03811012010-12-08 00:21:06 +02001026static void mgmt_pending_remove(struct pending_cmd *cmd)
1027{
1028 list_del(&cmd->list);
1029 mgmt_pending_free(cmd);
1030}
1031
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001032static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001033{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001034 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001035
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001036 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001037 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001038}
1039
Johan Hedberg8b064a32014-02-24 14:52:22 +02001040static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1041{
1042 BT_DBG("%s status 0x%02x", hdev->name, status);
1043
Johan Hedberga3172b72014-02-28 09:33:44 +02001044 if (hci_conn_count(hdev) == 0) {
1045 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001046 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001047 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001048}
1049
Johan Hedberg21a60d32014-06-10 14:05:58 +03001050static void hci_stop_discovery(struct hci_request *req)
1051{
1052 struct hci_dev *hdev = req->hdev;
1053 struct hci_cp_remote_name_req_cancel cp;
1054 struct inquiry_entry *e;
1055
1056 switch (hdev->discovery.state) {
1057 case DISCOVERY_FINDING:
1058 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1059 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1060 } else {
1061 cancel_delayed_work(&hdev->le_scan_disable);
1062 hci_req_add_le_scan_disable(req);
1063 }
1064
1065 break;
1066
1067 case DISCOVERY_RESOLVING:
1068 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1069 NAME_PENDING);
1070 if (!e)
1071 return;
1072
1073 bacpy(&cp.bdaddr, &e->data.bdaddr);
1074 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1075 &cp);
1076
1077 break;
1078
1079 default:
1080 /* Passive scanning */
1081 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1082 hci_req_add_le_scan_disable(req);
1083 break;
1084 }
1085}
1086
Johan Hedberg8b064a32014-02-24 14:52:22 +02001087static int clean_up_hci_state(struct hci_dev *hdev)
1088{
1089 struct hci_request req;
1090 struct hci_conn *conn;
1091
1092 hci_req_init(&req, hdev);
1093
1094 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1095 test_bit(HCI_PSCAN, &hdev->flags)) {
1096 u8 scan = 0x00;
1097 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1098 }
1099
1100 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1101 disable_advertising(&req);
1102
Johan Hedbergf8680f12014-06-10 14:05:59 +03001103 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001104
1105 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1106 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001107 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001108
Johan Hedbergc9910d02014-02-27 14:35:12 +02001109 switch (conn->state) {
1110 case BT_CONNECTED:
1111 case BT_CONFIG:
1112 dc.handle = cpu_to_le16(conn->handle);
1113 dc.reason = 0x15; /* Terminated due to Power Off */
1114 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1115 break;
1116 case BT_CONNECT:
1117 if (conn->type == LE_LINK)
1118 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1119 0, NULL);
1120 else if (conn->type == ACL_LINK)
1121 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1122 6, &conn->dst);
1123 break;
1124 case BT_CONNECT2:
1125 bacpy(&rej.bdaddr, &conn->dst);
1126 rej.reason = 0x15; /* Terminated due to Power Off */
1127 if (conn->type == ACL_LINK)
1128 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1129 sizeof(rej), &rej);
1130 else if (conn->type == SCO_LINK)
1131 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1132 sizeof(rej), &rej);
1133 break;
1134 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001135 }
1136
1137 return hci_req_run(&req, clean_up_hci_complete);
1138}
1139
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001140static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001141 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001142{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001143 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001144 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001145 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001147 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001148
Johan Hedberga7e80f22013-01-09 16:05:19 +02001149 if (cp->val != 0x00 && cp->val != 0x01)
1150 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1151 MGMT_STATUS_INVALID_PARAMS);
1152
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001153 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001154
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001155 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1156 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1157 MGMT_STATUS_BUSY);
1158 goto failed;
1159 }
1160
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001161 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1162 cancel_delayed_work(&hdev->power_off);
1163
1164 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001165 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1166 data, len);
1167 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001168 goto failed;
1169 }
1170 }
1171
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001172 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001173 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001174 goto failed;
1175 }
1176
Johan Hedberg03811012010-12-08 00:21:06 +02001177 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1178 if (!cmd) {
1179 err = -ENOMEM;
1180 goto failed;
1181 }
1182
Johan Hedberg8b064a32014-02-24 14:52:22 +02001183 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001184 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001185 err = 0;
1186 } else {
1187 /* Disconnect connections, stop scans, etc */
1188 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001189 if (!err)
1190 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1191 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001192
Johan Hedberg8b064a32014-02-24 14:52:22 +02001193 /* ENODATA means there were no HCI commands queued */
1194 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001195 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001196 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1197 err = 0;
1198 }
1199 }
Johan Hedberg03811012010-12-08 00:21:06 +02001200
1201failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001202 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 return err;
1204}
1205
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001206static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1207 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001208{
1209 struct sk_buff *skb;
1210 struct mgmt_hdr *hdr;
1211
Andre Guedes790eff42012-06-07 19:05:46 -03001212 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001213 if (!skb)
1214 return -ENOMEM;
1215
1216 hdr = (void *) skb_put(skb, sizeof(*hdr));
1217 hdr->opcode = cpu_to_le16(event);
1218 if (hdev)
1219 hdr->index = cpu_to_le16(hdev->id);
1220 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001221 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001222 hdr->len = cpu_to_le16(data_len);
1223
1224 if (data)
1225 memcpy(skb_put(skb, data_len), data, data_len);
1226
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001227 /* Time stamp */
1228 __net_timestamp(skb);
1229
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001230 hci_send_to_control(skb, skip_sk);
1231 kfree_skb(skb);
1232
1233 return 0;
1234}
1235
1236static int new_settings(struct hci_dev *hdev, struct sock *skip)
1237{
1238 __le32 ev;
1239
1240 ev = cpu_to_le32(get_current_settings(hdev));
1241
1242 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1243}
1244
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001245struct cmd_lookup {
1246 struct sock *sk;
1247 struct hci_dev *hdev;
1248 u8 mgmt_status;
1249};
1250
1251static void settings_rsp(struct pending_cmd *cmd, void *data)
1252{
1253 struct cmd_lookup *match = data;
1254
1255 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1256
1257 list_del(&cmd->list);
1258
1259 if (match->sk == NULL) {
1260 match->sk = cmd->sk;
1261 sock_hold(match->sk);
1262 }
1263
1264 mgmt_pending_free(cmd);
1265}
1266
1267static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1268{
1269 u8 *status = data;
1270
1271 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1272 mgmt_pending_remove(cmd);
1273}
1274
Johan Hedberge6fe7982013-10-02 15:45:22 +03001275static u8 mgmt_bredr_support(struct hci_dev *hdev)
1276{
1277 if (!lmp_bredr_capable(hdev))
1278 return MGMT_STATUS_NOT_SUPPORTED;
1279 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1280 return MGMT_STATUS_REJECTED;
1281 else
1282 return MGMT_STATUS_SUCCESS;
1283}
1284
1285static u8 mgmt_le_support(struct hci_dev *hdev)
1286{
1287 if (!lmp_le_capable(hdev))
1288 return MGMT_STATUS_NOT_SUPPORTED;
1289 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1290 return MGMT_STATUS_REJECTED;
1291 else
1292 return MGMT_STATUS_SUCCESS;
1293}
1294
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001295static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1296{
1297 struct pending_cmd *cmd;
1298 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001299 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001300 bool changed;
1301
1302 BT_DBG("status 0x%02x", status);
1303
1304 hci_dev_lock(hdev);
1305
1306 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1307 if (!cmd)
1308 goto unlock;
1309
1310 if (status) {
1311 u8 mgmt_err = mgmt_status(status);
1312 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001313 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001314 goto remove_cmd;
1315 }
1316
1317 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001318 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001319 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1320 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001321
1322 if (hdev->discov_timeout > 0) {
1323 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1324 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1325 to);
1326 }
1327 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001328 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1329 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001330 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001331
1332 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1333
1334 if (changed)
1335 new_settings(hdev, cmd->sk);
1336
Marcel Holtmann970ba522013-10-15 06:33:57 -07001337 /* When the discoverable mode gets changed, make sure
1338 * that class of device has the limited discoverable
1339 * bit correctly set.
1340 */
1341 hci_req_init(&req, hdev);
1342 update_class(&req);
1343 hci_req_run(&req, NULL);
1344
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001345remove_cmd:
1346 mgmt_pending_remove(cmd);
1347
1348unlock:
1349 hci_dev_unlock(hdev);
1350}
1351
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001352static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001353 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001354{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001355 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001356 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001357 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001358 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001359 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001360 int err;
1361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001362 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001363
Johan Hedberg9a43e252013-10-20 19:00:07 +03001364 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1365 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001366 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001367 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001368
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001369 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001370 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1371 MGMT_STATUS_INVALID_PARAMS);
1372
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001373 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001374
1375 /* Disabling discoverable requires that no timeout is set,
1376 * and enabling limited discoverable requires a timeout.
1377 */
1378 if ((cp->val == 0x00 && timeout > 0) ||
1379 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001380 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001381 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001382
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001383 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001384
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001385 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001386 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001387 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001388 goto failed;
1389 }
1390
1391 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001392 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001393 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001394 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001395 goto failed;
1396 }
1397
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001398 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001399 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001400 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001401 goto failed;
1402 }
1403
1404 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001405 bool changed = false;
1406
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001407 /* Setting limited discoverable when powered off is
1408 * not a valid operation since it requires a timeout
1409 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1410 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001411 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1412 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1413 changed = true;
1414 }
1415
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001416 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001417 if (err < 0)
1418 goto failed;
1419
1420 if (changed)
1421 err = new_settings(hdev, sk);
1422
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001423 goto failed;
1424 }
1425
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001426 /* If the current mode is the same, then just update the timeout
1427 * value with the new value. And if only the timeout gets updated,
1428 * then no need for any HCI transactions.
1429 */
1430 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1431 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1432 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001433 cancel_delayed_work(&hdev->discov_off);
1434 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001435
Marcel Holtmann36261542013-10-15 08:28:51 -07001436 if (cp->val && hdev->discov_timeout > 0) {
1437 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001438 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001439 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001440 }
1441
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001442 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001443 goto failed;
1444 }
1445
1446 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1447 if (!cmd) {
1448 err = -ENOMEM;
1449 goto failed;
1450 }
1451
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001452 /* Cancel any potential discoverable timeout that might be
1453 * still active and store new timeout value. The arming of
1454 * the timeout happens in the complete handler.
1455 */
1456 cancel_delayed_work(&hdev->discov_off);
1457 hdev->discov_timeout = timeout;
1458
Johan Hedbergb456f872013-10-19 23:38:22 +03001459 /* Limited discoverable mode */
1460 if (cp->val == 0x02)
1461 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1462 else
1463 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1464
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001465 hci_req_init(&req, hdev);
1466
Johan Hedberg9a43e252013-10-20 19:00:07 +03001467 /* The procedure for LE-only controllers is much simpler - just
1468 * update the advertising data.
1469 */
1470 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1471 goto update_ad;
1472
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001473 scan = SCAN_PAGE;
1474
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001475 if (cp->val) {
1476 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001477
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001478 if (cp->val == 0x02) {
1479 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001480 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001481 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1482 hci_cp.iac_lap[1] = 0x8b;
1483 hci_cp.iac_lap[2] = 0x9e;
1484 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1485 hci_cp.iac_lap[4] = 0x8b;
1486 hci_cp.iac_lap[5] = 0x9e;
1487 } else {
1488 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001489 hci_cp.num_iac = 1;
1490 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1491 hci_cp.iac_lap[1] = 0x8b;
1492 hci_cp.iac_lap[2] = 0x9e;
1493 }
1494
1495 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1496 (hci_cp.num_iac * 3) + 1, &hci_cp);
1497
1498 scan |= SCAN_INQUIRY;
1499 } else {
1500 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1501 }
1502
1503 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504
Johan Hedberg9a43e252013-10-20 19:00:07 +03001505update_ad:
1506 update_adv_data(&req);
1507
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001508 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001509 if (err < 0)
1510 mgmt_pending_remove(cmd);
1511
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001512failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001513 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001514 return err;
1515}
1516
Johan Hedberg406d7802013-03-15 17:07:09 -05001517static void write_fast_connectable(struct hci_request *req, bool enable)
1518{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001519 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001520 struct hci_cp_write_page_scan_activity acp;
1521 u8 type;
1522
Johan Hedberg547003b2013-10-21 16:51:53 +03001523 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1524 return;
1525
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001526 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1527 return;
1528
Johan Hedberg406d7802013-03-15 17:07:09 -05001529 if (enable) {
1530 type = PAGE_SCAN_TYPE_INTERLACED;
1531
1532 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001533 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001534 } else {
1535 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1536
1537 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001538 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001539 }
1540
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001541 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001542
Johan Hedbergbd98b992013-03-15 17:07:13 -05001543 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1544 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1545 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1546 sizeof(acp), &acp);
1547
1548 if (hdev->page_scan_type != type)
1549 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001550}
1551
Johan Hedberg2b76f452013-03-15 17:07:04 -05001552static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1553{
1554 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001555 struct mgmt_mode *cp;
1556 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001557
1558 BT_DBG("status 0x%02x", status);
1559
1560 hci_dev_lock(hdev);
1561
1562 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1563 if (!cmd)
1564 goto unlock;
1565
Johan Hedberg37438c12013-10-14 16:20:05 +03001566 if (status) {
1567 u8 mgmt_err = mgmt_status(status);
1568 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1569 goto remove_cmd;
1570 }
1571
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001572 cp = cmd->param;
1573 if (cp->val)
1574 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1575 else
1576 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1577
Johan Hedberg2b76f452013-03-15 17:07:04 -05001578 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1579
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001580 if (changed)
1581 new_settings(hdev, cmd->sk);
1582
Johan Hedberg37438c12013-10-14 16:20:05 +03001583remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001584 mgmt_pending_remove(cmd);
1585
1586unlock:
1587 hci_dev_unlock(hdev);
1588}
1589
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001590static int set_connectable_update_settings(struct hci_dev *hdev,
1591 struct sock *sk, u8 val)
1592{
1593 bool changed = false;
1594 int err;
1595
1596 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1597 changed = true;
1598
1599 if (val) {
1600 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1601 } else {
1602 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1603 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1604 }
1605
1606 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1607 if (err < 0)
1608 return err;
1609
1610 if (changed)
1611 return new_settings(hdev, sk);
1612
1613 return 0;
1614}
1615
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001616static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001617 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001618{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001619 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001620 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001621 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001622 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001623 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001624
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001625 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001626
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001627 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1628 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001629 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001630 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001631
Johan Hedberga7e80f22013-01-09 16:05:19 +02001632 if (cp->val != 0x00 && cp->val != 0x01)
1633 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1634 MGMT_STATUS_INVALID_PARAMS);
1635
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001636 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001637
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001638 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001639 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001640 goto failed;
1641 }
1642
1643 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001644 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001645 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001646 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001647 goto failed;
1648 }
1649
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001650 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1651 if (!cmd) {
1652 err = -ENOMEM;
1653 goto failed;
1654 }
1655
Johan Hedberg2b76f452013-03-15 17:07:04 -05001656 hci_req_init(&req, hdev);
1657
Johan Hedberg9a43e252013-10-20 19:00:07 +03001658 /* If BR/EDR is not enabled and we disable advertising as a
1659 * by-product of disabling connectable, we need to update the
1660 * advertising flags.
1661 */
1662 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1663 if (!cp->val) {
1664 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1665 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1666 }
1667 update_adv_data(&req);
1668 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001669 if (cp->val) {
1670 scan = SCAN_PAGE;
1671 } else {
1672 scan = 0;
1673
1674 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001675 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001676 cancel_delayed_work(&hdev->discov_off);
1677 }
1678
1679 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1680 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001681
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001682 /* If we're going from non-connectable to connectable or
1683 * vice-versa when fast connectable is enabled ensure that fast
1684 * connectable gets disabled. write_fast_connectable won't do
1685 * anything if the page scan parameters are already what they
1686 * should be.
1687 */
1688 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001689 write_fast_connectable(&req, false);
1690
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001691 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1692 hci_conn_num(hdev, LE_LINK) == 0) {
1693 disable_advertising(&req);
1694 enable_advertising(&req);
1695 }
1696
Johan Hedberg2b76f452013-03-15 17:07:04 -05001697 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001698 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001699 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001700 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001701 err = set_connectable_update_settings(hdev, sk,
1702 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001703 goto failed;
1704 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001705
1706failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001707 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001708 return err;
1709}
1710
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001711static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001712 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001713{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001714 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001715 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001716 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001717
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001718 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001719
Johan Hedberga7e80f22013-01-09 16:05:19 +02001720 if (cp->val != 0x00 && cp->val != 0x01)
1721 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1722 MGMT_STATUS_INVALID_PARAMS);
1723
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001724 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001725
1726 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001727 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001728 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001729 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001730
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001731 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001732 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001733 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001734
Marcel Holtmann55594352013-10-06 16:11:57 -07001735 if (changed)
1736 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001737
Marcel Holtmann55594352013-10-06 16:11:57 -07001738unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001739 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001740 return err;
1741}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001742
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001743static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1744 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001745{
1746 struct mgmt_mode *cp = data;
1747 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001748 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001749 int err;
1750
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001751 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001752
Johan Hedberge6fe7982013-10-02 15:45:22 +03001753 status = mgmt_bredr_support(hdev);
1754 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001755 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001756 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001757
Johan Hedberga7e80f22013-01-09 16:05:19 +02001758 if (cp->val != 0x00 && cp->val != 0x01)
1759 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1760 MGMT_STATUS_INVALID_PARAMS);
1761
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001762 hci_dev_lock(hdev);
1763
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001764 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001765 bool changed = false;
1766
1767 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001768 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001769 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1770 changed = true;
1771 }
1772
1773 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1774 if (err < 0)
1775 goto failed;
1776
1777 if (changed)
1778 err = new_settings(hdev, sk);
1779
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001780 goto failed;
1781 }
1782
1783 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001784 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001785 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001786 goto failed;
1787 }
1788
1789 val = !!cp->val;
1790
1791 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1792 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1793 goto failed;
1794 }
1795
1796 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1797 if (!cmd) {
1798 err = -ENOMEM;
1799 goto failed;
1800 }
1801
1802 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1803 if (err < 0) {
1804 mgmt_pending_remove(cmd);
1805 goto failed;
1806 }
1807
1808failed:
1809 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001810 return err;
1811}
1812
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001813static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001814{
1815 struct mgmt_mode *cp = data;
1816 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001817 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001818 int err;
1819
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001820 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001821
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001822 status = mgmt_bredr_support(hdev);
1823 if (status)
1824 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1825
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001826 if (!lmp_ssp_capable(hdev))
1827 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1828 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001829
Johan Hedberga7e80f22013-01-09 16:05:19 +02001830 if (cp->val != 0x00 && cp->val != 0x01)
1831 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1832 MGMT_STATUS_INVALID_PARAMS);
1833
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001834 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001835
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001836 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001837 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001838
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001839 if (cp->val) {
1840 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1841 &hdev->dev_flags);
1842 } else {
1843 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1844 &hdev->dev_flags);
1845 if (!changed)
1846 changed = test_and_clear_bit(HCI_HS_ENABLED,
1847 &hdev->dev_flags);
1848 else
1849 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001850 }
1851
1852 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1853 if (err < 0)
1854 goto failed;
1855
1856 if (changed)
1857 err = new_settings(hdev, sk);
1858
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001859 goto failed;
1860 }
1861
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001862 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1863 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001864 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1865 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001866 goto failed;
1867 }
1868
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001869 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001870 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1871 goto failed;
1872 }
1873
1874 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1875 if (!cmd) {
1876 err = -ENOMEM;
1877 goto failed;
1878 }
1879
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001880 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001881 if (err < 0) {
1882 mgmt_pending_remove(cmd);
1883 goto failed;
1884 }
1885
1886failed:
1887 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001888 return err;
1889}
1890
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001891static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001892{
1893 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001894 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001895 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001896 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001898 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001899
Johan Hedberge6fe7982013-10-02 15:45:22 +03001900 status = mgmt_bredr_support(hdev);
1901 if (status)
1902 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001903
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001904 if (!lmp_ssp_capable(hdev))
1905 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1906 MGMT_STATUS_NOT_SUPPORTED);
1907
1908 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1909 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1910 MGMT_STATUS_REJECTED);
1911
Johan Hedberga7e80f22013-01-09 16:05:19 +02001912 if (cp->val != 0x00 && cp->val != 0x01)
1913 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1914 MGMT_STATUS_INVALID_PARAMS);
1915
Marcel Holtmannee392692013-10-01 22:59:23 -07001916 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001917
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001918 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001919 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001920 } else {
1921 if (hdev_is_powered(hdev)) {
1922 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1923 MGMT_STATUS_REJECTED);
1924 goto unlock;
1925 }
1926
Marcel Holtmannee392692013-10-01 22:59:23 -07001927 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001928 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001929
1930 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1931 if (err < 0)
1932 goto unlock;
1933
1934 if (changed)
1935 err = new_settings(hdev, sk);
1936
1937unlock:
1938 hci_dev_unlock(hdev);
1939 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001940}
1941
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001942static void le_enable_complete(struct hci_dev *hdev, u8 status)
1943{
1944 struct cmd_lookup match = { NULL, hdev };
1945
1946 if (status) {
1947 u8 mgmt_err = mgmt_status(status);
1948
1949 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1950 &mgmt_err);
1951 return;
1952 }
1953
1954 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1955
1956 new_settings(hdev, match.sk);
1957
1958 if (match.sk)
1959 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001960
1961 /* Make sure the controller has a good default for
1962 * advertising data. Restrict the update to when LE
1963 * has actually been enabled. During power on, the
1964 * update in powered_update_hci will take care of it.
1965 */
1966 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1967 struct hci_request req;
1968
1969 hci_dev_lock(hdev);
1970
1971 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001972 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001973 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001974 hci_req_run(&req, NULL);
1975
1976 hci_dev_unlock(hdev);
1977 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001978}
1979
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001980static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001981{
1982 struct mgmt_mode *cp = data;
1983 struct hci_cp_write_le_host_supported hci_cp;
1984 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001985 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001986 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001987 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001988
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001989 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001990
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001991 if (!lmp_le_capable(hdev))
1992 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1993 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001994
Johan Hedberga7e80f22013-01-09 16:05:19 +02001995 if (cp->val != 0x00 && cp->val != 0x01)
1996 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1997 MGMT_STATUS_INVALID_PARAMS);
1998
Johan Hedbergc73eee92013-04-19 18:35:21 +03001999 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002000 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002001 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2002 MGMT_STATUS_REJECTED);
2003
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002004 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002005
2006 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002007 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002008
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002009 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002010 bool changed = false;
2011
2012 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2013 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2014 changed = true;
2015 }
2016
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002017 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2018 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002019 changed = true;
2020 }
2021
Johan Hedberg06199cf2012-02-22 16:37:11 +02002022 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2023 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002024 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002025
2026 if (changed)
2027 err = new_settings(hdev, sk);
2028
Johan Hedberg1de028c2012-02-29 19:55:35 -08002029 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002030 }
2031
Johan Hedberg4375f102013-09-25 13:26:10 +03002032 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2033 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002034 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002035 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002036 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002037 }
2038
2039 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2040 if (!cmd) {
2041 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002042 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002043 }
2044
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002045 hci_req_init(&req, hdev);
2046
Johan Hedberg06199cf2012-02-22 16:37:11 +02002047 memset(&hci_cp, 0, sizeof(hci_cp));
2048
2049 if (val) {
2050 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002051 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002052 } else {
2053 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2054 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002055 }
2056
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002057 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2058 &hci_cp);
2059
2060 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302061 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002062 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002063
Johan Hedberg1de028c2012-02-29 19:55:35 -08002064unlock:
2065 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002066 return err;
2067}
2068
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002069/* This is a helper function to test for pending mgmt commands that can
2070 * cause CoD or EIR HCI commands. We can only allow one such pending
2071 * mgmt command at a time since otherwise we cannot easily track what
2072 * the current values are, will be, and based on that calculate if a new
2073 * HCI command needs to be sent and if yes with what value.
2074 */
2075static bool pending_eir_or_class(struct hci_dev *hdev)
2076{
2077 struct pending_cmd *cmd;
2078
2079 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2080 switch (cmd->opcode) {
2081 case MGMT_OP_ADD_UUID:
2082 case MGMT_OP_REMOVE_UUID:
2083 case MGMT_OP_SET_DEV_CLASS:
2084 case MGMT_OP_SET_POWERED:
2085 return true;
2086 }
2087 }
2088
2089 return false;
2090}
2091
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002092static const u8 bluetooth_base_uuid[] = {
2093 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2094 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2095};
2096
2097static u8 get_uuid_size(const u8 *uuid)
2098{
2099 u32 val;
2100
2101 if (memcmp(uuid, bluetooth_base_uuid, 12))
2102 return 128;
2103
2104 val = get_unaligned_le32(&uuid[12]);
2105 if (val > 0xffff)
2106 return 32;
2107
2108 return 16;
2109}
2110
Johan Hedberg92da6092013-03-15 17:06:55 -05002111static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2112{
2113 struct pending_cmd *cmd;
2114
2115 hci_dev_lock(hdev);
2116
2117 cmd = mgmt_pending_find(mgmt_op, hdev);
2118 if (!cmd)
2119 goto unlock;
2120
2121 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2122 hdev->dev_class, 3);
2123
2124 mgmt_pending_remove(cmd);
2125
2126unlock:
2127 hci_dev_unlock(hdev);
2128}
2129
2130static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2131{
2132 BT_DBG("status 0x%02x", status);
2133
2134 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2135}
2136
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002137static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002138{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002139 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002140 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002141 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002142 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002143 int err;
2144
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002145 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002146
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002147 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002148
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002149 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002150 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002151 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002152 goto failed;
2153 }
2154
Andre Guedes92c4c202012-06-07 19:05:44 -03002155 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002156 if (!uuid) {
2157 err = -ENOMEM;
2158 goto failed;
2159 }
2160
2161 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002162 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002163 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002164
Johan Hedbergde66aa62013-01-27 00:31:27 +02002165 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002166
Johan Hedberg890ea892013-03-15 17:06:52 -05002167 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002168
Johan Hedberg890ea892013-03-15 17:06:52 -05002169 update_class(&req);
2170 update_eir(&req);
2171
Johan Hedberg92da6092013-03-15 17:06:55 -05002172 err = hci_req_run(&req, add_uuid_complete);
2173 if (err < 0) {
2174 if (err != -ENODATA)
2175 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002176
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002177 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002178 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002179 goto failed;
2180 }
2181
2182 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002183 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002184 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002185 goto failed;
2186 }
2187
2188 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002189
2190failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002191 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002192 return err;
2193}
2194
Johan Hedberg24b78d02012-02-23 23:24:30 +02002195static bool enable_service_cache(struct hci_dev *hdev)
2196{
2197 if (!hdev_is_powered(hdev))
2198 return false;
2199
2200 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002201 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2202 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002203 return true;
2204 }
2205
2206 return false;
2207}
2208
Johan Hedberg92da6092013-03-15 17:06:55 -05002209static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2210{
2211 BT_DBG("status 0x%02x", status);
2212
2213 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2214}
2215
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002216static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002217 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002218{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002219 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002220 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002221 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002222 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 -05002223 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002224 int err, found;
2225
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002226 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002227
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002228 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002229
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002230 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002231 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002232 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002233 goto unlock;
2234 }
2235
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002236 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002237 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002238
Johan Hedberg24b78d02012-02-23 23:24:30 +02002239 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002240 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002241 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002242 goto unlock;
2243 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002244
Johan Hedberg9246a862012-02-23 21:33:16 +02002245 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002246 }
2247
2248 found = 0;
2249
Johan Hedberg056341c2013-01-27 00:31:30 +02002250 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002251 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2252 continue;
2253
2254 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002255 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002256 found++;
2257 }
2258
2259 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002260 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002261 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002262 goto unlock;
2263 }
2264
Johan Hedberg9246a862012-02-23 21:33:16 +02002265update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002266 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002267
Johan Hedberg890ea892013-03-15 17:06:52 -05002268 update_class(&req);
2269 update_eir(&req);
2270
Johan Hedberg92da6092013-03-15 17:06:55 -05002271 err = hci_req_run(&req, remove_uuid_complete);
2272 if (err < 0) {
2273 if (err != -ENODATA)
2274 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002275
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002276 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002277 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002278 goto unlock;
2279 }
2280
2281 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002282 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002283 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002284 goto unlock;
2285 }
2286
2287 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002288
2289unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002290 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002291 return err;
2292}
2293
Johan Hedberg92da6092013-03-15 17:06:55 -05002294static void set_class_complete(struct hci_dev *hdev, u8 status)
2295{
2296 BT_DBG("status 0x%02x", status);
2297
2298 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2299}
2300
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002301static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002302 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002303{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002304 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002305 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002306 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002307 int err;
2308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002309 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002310
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002311 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002312 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2313 MGMT_STATUS_NOT_SUPPORTED);
2314
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002315 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002316
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002317 if (pending_eir_or_class(hdev)) {
2318 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2319 MGMT_STATUS_BUSY);
2320 goto unlock;
2321 }
2322
2323 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2324 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2325 MGMT_STATUS_INVALID_PARAMS);
2326 goto unlock;
2327 }
2328
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002329 hdev->major_class = cp->major;
2330 hdev->minor_class = cp->minor;
2331
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002332 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002333 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002334 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002335 goto unlock;
2336 }
2337
Johan Hedberg890ea892013-03-15 17:06:52 -05002338 hci_req_init(&req, hdev);
2339
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002340 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002341 hci_dev_unlock(hdev);
2342 cancel_delayed_work_sync(&hdev->service_cache);
2343 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002344 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002345 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002346
Johan Hedberg890ea892013-03-15 17:06:52 -05002347 update_class(&req);
2348
Johan Hedberg92da6092013-03-15 17:06:55 -05002349 err = hci_req_run(&req, set_class_complete);
2350 if (err < 0) {
2351 if (err != -ENODATA)
2352 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002354 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002355 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002356 goto unlock;
2357 }
2358
2359 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002360 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002361 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002362 goto unlock;
2363 }
2364
2365 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002366
Johan Hedbergb5235a62012-02-21 14:32:24 +02002367unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002368 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002369 return err;
2370}
2371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002372static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002373 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002374{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002375 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002376 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002377 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002378 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002379
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002380 BT_DBG("request for %s", hdev->name);
2381
2382 if (!lmp_bredr_capable(hdev))
2383 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2384 MGMT_STATUS_NOT_SUPPORTED);
2385
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002386 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002387
Johan Hedberg86742e12011-11-07 23:13:38 +02002388 expected_len = sizeof(*cp) + key_count *
2389 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002390 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002391 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002392 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002393 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002394 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002395 }
2396
Johan Hedberg4ae14302013-01-20 14:27:13 +02002397 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2398 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2399 MGMT_STATUS_INVALID_PARAMS);
2400
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002401 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002402 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002403
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002404 for (i = 0; i < key_count; i++) {
2405 struct mgmt_link_key_info *key = &cp->keys[i];
2406
Marcel Holtmann8e991132014-01-10 02:07:25 -08002407 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002408 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2409 MGMT_STATUS_INVALID_PARAMS);
2410 }
2411
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002412 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002413
2414 hci_link_keys_clear(hdev);
2415
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002416 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002417 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2418 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002419 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002420 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2421 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002422
2423 if (changed)
2424 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002425
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002426 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002427 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002428
Johan Hedberg7652ff62014-06-24 13:15:49 +03002429 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2430 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002431 }
2432
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002433 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002434
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002435 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002436
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002437 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002438}
2439
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002440static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002441 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002442{
2443 struct mgmt_ev_device_unpaired ev;
2444
2445 bacpy(&ev.addr.bdaddr, bdaddr);
2446 ev.addr.type = addr_type;
2447
2448 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002449 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002450}
2451
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002452static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002453 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002454{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002455 struct mgmt_cp_unpair_device *cp = data;
2456 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002457 struct hci_cp_disconnect dc;
2458 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002459 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002460 int err;
2461
Johan Hedberga8a1d192011-11-10 15:54:38 +02002462 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002463 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2464 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002465
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002466 if (!bdaddr_type_is_valid(cp->addr.type))
2467 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2468 MGMT_STATUS_INVALID_PARAMS,
2469 &rp, sizeof(rp));
2470
Johan Hedberg118da702013-01-20 14:27:20 +02002471 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2472 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2473 MGMT_STATUS_INVALID_PARAMS,
2474 &rp, sizeof(rp));
2475
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002476 hci_dev_lock(hdev);
2477
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002478 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002479 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002480 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002481 goto unlock;
2482 }
2483
Johan Hedberge0b2b272014-02-18 17:14:31 +02002484 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002485 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002486 } else {
2487 u8 addr_type;
2488
2489 if (cp->addr.type == BDADDR_LE_PUBLIC)
2490 addr_type = ADDR_LE_DEV_PUBLIC;
2491 else
2492 addr_type = ADDR_LE_DEV_RANDOM;
2493
Johan Hedberga7ec7332014-02-18 17:14:35 +02002494 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2495
Andre Guedesa9b0a042014-02-26 20:21:52 -03002496 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2497
Johan Hedberge0b2b272014-02-18 17:14:31 +02002498 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2499 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002500
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002501 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002502 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002503 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002504 goto unlock;
2505 }
2506
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002507 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002508 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002509 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002510 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002511 else
2512 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002513 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002514 } else {
2515 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002516 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002517
Johan Hedberga8a1d192011-11-10 15:54:38 +02002518 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002519 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002520 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002521 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002522 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002523 }
2524
Johan Hedberg124f6e32012-02-09 13:50:12 +02002525 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002526 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002527 if (!cmd) {
2528 err = -ENOMEM;
2529 goto unlock;
2530 }
2531
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002532 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002533 dc.reason = 0x13; /* Remote User Terminated Connection */
2534 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2535 if (err < 0)
2536 mgmt_pending_remove(cmd);
2537
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002538unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002539 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002540 return err;
2541}
2542
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002543static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002544 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002545{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002546 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002547 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002548 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002549 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002550 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002551 int err;
2552
2553 BT_DBG("");
2554
Johan Hedberg06a63b12013-01-20 14:27:21 +02002555 memset(&rp, 0, sizeof(rp));
2556 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2557 rp.addr.type = cp->addr.type;
2558
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002559 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002560 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2561 MGMT_STATUS_INVALID_PARAMS,
2562 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002563
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002564 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002565
2566 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002567 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2568 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002569 goto failed;
2570 }
2571
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002572 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002573 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2574 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002575 goto failed;
2576 }
2577
Andre Guedes591f47f2012-04-24 21:02:49 -03002578 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002579 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2580 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002581 else
2582 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002583
Vishal Agarwalf9607272012-06-13 05:32:43 +05302584 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002585 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2586 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002587 goto failed;
2588 }
2589
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002590 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002591 if (!cmd) {
2592 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002593 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002594 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002595
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002596 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002597 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002598
2599 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2600 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002601 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002602
2603failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002604 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002605 return err;
2606}
2607
Andre Guedes57c14772012-04-24 21:02:50 -03002608static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002609{
2610 switch (link_type) {
2611 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002612 switch (addr_type) {
2613 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002614 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002615
Johan Hedberg48264f02011-11-09 13:58:58 +02002616 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002617 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002618 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002619 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002620
Johan Hedberg4c659c32011-11-07 23:13:39 +02002621 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002622 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002623 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002624 }
2625}
2626
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002627static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2628 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002629{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002630 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002631 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002632 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002633 int err;
2634 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002635
2636 BT_DBG("");
2637
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002638 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002639
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002640 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002641 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002642 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002643 goto unlock;
2644 }
2645
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002646 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002647 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2648 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002649 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002650 }
2651
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002652 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002653 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002654 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002655 err = -ENOMEM;
2656 goto unlock;
2657 }
2658
Johan Hedberg2784eb42011-01-21 13:56:35 +02002659 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002660 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002661 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2662 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002663 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002664 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002665 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002666 continue;
2667 i++;
2668 }
2669
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002670 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002671
Johan Hedberg4c659c32011-11-07 23:13:39 +02002672 /* Recalculate length in case of filtered SCO connections, etc */
2673 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002674
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002675 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002676 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002677
Johan Hedberga38528f2011-01-22 06:46:43 +02002678 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002679
2680unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002681 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002682 return err;
2683}
2684
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002685static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002686 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002687{
2688 struct pending_cmd *cmd;
2689 int err;
2690
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002691 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002692 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002693 if (!cmd)
2694 return -ENOMEM;
2695
Johan Hedbergd8457692012-02-17 14:24:57 +02002696 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002697 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002698 if (err < 0)
2699 mgmt_pending_remove(cmd);
2700
2701 return err;
2702}
2703
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002704static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002705 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002706{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002707 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002708 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002709 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002710 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002711 int err;
2712
2713 BT_DBG("");
2714
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002715 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002716
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002717 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002718 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002719 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002720 goto failed;
2721 }
2722
Johan Hedbergd8457692012-02-17 14:24:57 +02002723 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002724 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002725 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002726 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002727 goto failed;
2728 }
2729
2730 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002731 struct mgmt_cp_pin_code_neg_reply ncp;
2732
2733 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002734
2735 BT_ERR("PIN code is not 16 bytes long");
2736
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002737 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002738 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002739 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002740 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002741
2742 goto failed;
2743 }
2744
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002745 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002746 if (!cmd) {
2747 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002748 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002749 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002750
Johan Hedbergd8457692012-02-17 14:24:57 +02002751 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002752 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002753 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002754
2755 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2756 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002757 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002758
2759failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002760 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002761 return err;
2762}
2763
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002764static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2765 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002766{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002767 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002768
2769 BT_DBG("");
2770
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002771 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2772 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2773 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2774
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002775 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002776
2777 hdev->io_capability = cp->io_capability;
2778
2779 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002780 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002781
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002782 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002783
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002784 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2785 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002786}
2787
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002788static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002789{
2790 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002791 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002792
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002793 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002794 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2795 continue;
2796
Johan Hedberge9a416b2011-02-19 12:05:56 -03002797 if (cmd->user_data != conn)
2798 continue;
2799
2800 return cmd;
2801 }
2802
2803 return NULL;
2804}
2805
2806static void pairing_complete(struct pending_cmd *cmd, u8 status)
2807{
2808 struct mgmt_rp_pair_device rp;
2809 struct hci_conn *conn = cmd->user_data;
2810
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002811 bacpy(&rp.addr.bdaddr, &conn->dst);
2812 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002813
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002814 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002815 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002816
2817 /* So we don't get further callbacks for this connection */
2818 conn->connect_cfm_cb = NULL;
2819 conn->security_cfm_cb = NULL;
2820 conn->disconn_cfm_cb = NULL;
2821
David Herrmann76a68ba2013-04-06 20:28:37 +02002822 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002823
Johan Hedberga664b5b2011-02-19 12:06:02 -03002824 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002825}
2826
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002827void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2828{
2829 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2830 struct pending_cmd *cmd;
2831
2832 cmd = find_pairing(conn);
2833 if (cmd)
2834 pairing_complete(cmd, status);
2835}
2836
Johan Hedberge9a416b2011-02-19 12:05:56 -03002837static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2838{
2839 struct pending_cmd *cmd;
2840
2841 BT_DBG("status %u", status);
2842
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002843 cmd = find_pairing(conn);
2844 if (!cmd)
2845 BT_DBG("Unable to find a pending command");
2846 else
Johan Hedberge2113262012-02-18 15:20:03 +02002847 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002848}
2849
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002850static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302851{
2852 struct pending_cmd *cmd;
2853
2854 BT_DBG("status %u", status);
2855
2856 if (!status)
2857 return;
2858
2859 cmd = find_pairing(conn);
2860 if (!cmd)
2861 BT_DBG("Unable to find a pending command");
2862 else
2863 pairing_complete(cmd, mgmt_status(status));
2864}
2865
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002866static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002867 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002868{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002869 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002870 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002871 struct pending_cmd *cmd;
2872 u8 sec_level, auth_type;
2873 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002874 int err;
2875
2876 BT_DBG("");
2877
Szymon Jancf950a30e2013-01-18 12:48:07 +01002878 memset(&rp, 0, sizeof(rp));
2879 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2880 rp.addr.type = cp->addr.type;
2881
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002882 if (!bdaddr_type_is_valid(cp->addr.type))
2883 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2884 MGMT_STATUS_INVALID_PARAMS,
2885 &rp, sizeof(rp));
2886
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002887 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2888 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2889 MGMT_STATUS_INVALID_PARAMS,
2890 &rp, sizeof(rp));
2891
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002892 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002893
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002894 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002895 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2896 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002897 goto unlock;
2898 }
2899
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002900 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002901 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002902
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002903 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002904 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2905 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002906 } else {
2907 u8 addr_type;
2908
2909 /* Convert from L2CAP channel address type to HCI address type
2910 */
2911 if (cp->addr.type == BDADDR_LE_PUBLIC)
2912 addr_type = ADDR_LE_DEV_PUBLIC;
2913 else
2914 addr_type = ADDR_LE_DEV_RANDOM;
2915
2916 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002917 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002918 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002919
Ville Tervo30e76272011-02-22 16:10:53 -03002920 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002921 int status;
2922
2923 if (PTR_ERR(conn) == -EBUSY)
2924 status = MGMT_STATUS_BUSY;
2925 else
2926 status = MGMT_STATUS_CONNECT_FAILED;
2927
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002928 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002929 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002930 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002931 goto unlock;
2932 }
2933
2934 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002935 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002936 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002937 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002938 goto unlock;
2939 }
2940
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002941 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002942 if (!cmd) {
2943 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002944 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002945 goto unlock;
2946 }
2947
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002948 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002949 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002950 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002951 conn->security_cfm_cb = pairing_complete_cb;
2952 conn->disconn_cfm_cb = pairing_complete_cb;
2953 } else {
2954 conn->connect_cfm_cb = le_pairing_complete_cb;
2955 conn->security_cfm_cb = le_pairing_complete_cb;
2956 conn->disconn_cfm_cb = le_pairing_complete_cb;
2957 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002958
Johan Hedberge9a416b2011-02-19 12:05:56 -03002959 conn->io_capability = cp->io_cap;
2960 cmd->user_data = conn;
2961
2962 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002963 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002964 pairing_complete(cmd, 0);
2965
2966 err = 0;
2967
2968unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002969 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002970 return err;
2971}
2972
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002973static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2974 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002975{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002976 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002977 struct pending_cmd *cmd;
2978 struct hci_conn *conn;
2979 int err;
2980
2981 BT_DBG("");
2982
Johan Hedberg28424702012-02-02 04:02:29 +02002983 hci_dev_lock(hdev);
2984
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002985 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002986 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002987 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002988 goto unlock;
2989 }
2990
Johan Hedberg28424702012-02-02 04:02:29 +02002991 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2992 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002993 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002994 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002995 goto unlock;
2996 }
2997
2998 conn = cmd->user_data;
2999
3000 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003001 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003002 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003003 goto unlock;
3004 }
3005
3006 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3007
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003008 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003009 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003010unlock:
3011 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003012 return err;
3013}
3014
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003015static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003016 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003017 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003018{
Johan Hedberga5c29682011-02-19 12:05:57 -03003019 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003020 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003021 int err;
3022
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003023 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003024
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003025 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003026 err = cmd_complete(sk, hdev->id, mgmt_op,
3027 MGMT_STATUS_NOT_POWERED, addr,
3028 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003029 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003030 }
3031
Johan Hedberg1707c602013-03-15 17:07:15 -05003032 if (addr->type == BDADDR_BREDR)
3033 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003034 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003035 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003036
Johan Hedberg272d90d2012-02-09 15:26:12 +02003037 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003038 err = cmd_complete(sk, hdev->id, mgmt_op,
3039 MGMT_STATUS_NOT_CONNECTED, addr,
3040 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003041 goto done;
3042 }
3043
Johan Hedberg1707c602013-03-15 17:07:15 -05003044 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Johan Hedbergc73f94b2014-06-13 10:22:28 +03003045 /* Continue with pairing via SMP. The hdev lock must be
3046 * released as SMP may try to recquire it for crypto
3047 * purposes.
3048 */
3049 hci_dev_unlock(hdev);
Brian Gix5fe57d92011-12-21 16:12:13 -08003050 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Johan Hedbergc73f94b2014-06-13 10:22:28 +03003051 hci_dev_lock(hdev);
Brian Gix47c15e22011-11-16 13:53:14 -08003052
Brian Gix5fe57d92011-12-21 16:12:13 -08003053 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003054 err = cmd_complete(sk, hdev->id, mgmt_op,
3055 MGMT_STATUS_SUCCESS, addr,
3056 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003057 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003058 err = cmd_complete(sk, hdev->id, mgmt_op,
3059 MGMT_STATUS_FAILED, addr,
3060 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003061
Brian Gix47c15e22011-11-16 13:53:14 -08003062 goto done;
3063 }
3064
Johan Hedberg1707c602013-03-15 17:07:15 -05003065 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003066 if (!cmd) {
3067 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003068 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003069 }
3070
Brian Gix0df4c182011-11-16 13:53:13 -08003071 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003072 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3073 struct hci_cp_user_passkey_reply cp;
3074
Johan Hedberg1707c602013-03-15 17:07:15 -05003075 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003076 cp.passkey = passkey;
3077 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3078 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003079 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3080 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003081
Johan Hedberga664b5b2011-02-19 12:06:02 -03003082 if (err < 0)
3083 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003084
Brian Gix0df4c182011-11-16 13:53:13 -08003085done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003086 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003087 return err;
3088}
3089
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303090static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3091 void *data, u16 len)
3092{
3093 struct mgmt_cp_pin_code_neg_reply *cp = data;
3094
3095 BT_DBG("");
3096
Johan Hedberg1707c602013-03-15 17:07:15 -05003097 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303098 MGMT_OP_PIN_CODE_NEG_REPLY,
3099 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3100}
3101
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003102static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3103 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003104{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003105 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003106
3107 BT_DBG("");
3108
3109 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003110 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003111 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003112
Johan Hedberg1707c602013-03-15 17:07:15 -05003113 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003114 MGMT_OP_USER_CONFIRM_REPLY,
3115 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003116}
3117
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003118static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003119 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003120{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003121 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003122
3123 BT_DBG("");
3124
Johan Hedberg1707c602013-03-15 17:07:15 -05003125 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003126 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3127 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003128}
3129
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003130static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3131 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003132{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003133 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003134
3135 BT_DBG("");
3136
Johan Hedberg1707c602013-03-15 17:07:15 -05003137 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003138 MGMT_OP_USER_PASSKEY_REPLY,
3139 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003140}
3141
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003142static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003143 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003144{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003145 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003146
3147 BT_DBG("");
3148
Johan Hedberg1707c602013-03-15 17:07:15 -05003149 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003150 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3151 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003152}
3153
Johan Hedberg13928972013-03-15 17:07:00 -05003154static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003155{
Johan Hedberg13928972013-03-15 17:07:00 -05003156 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003157 struct hci_cp_write_local_name cp;
3158
Johan Hedberg13928972013-03-15 17:07:00 -05003159 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003160
Johan Hedberg890ea892013-03-15 17:06:52 -05003161 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003162}
3163
Johan Hedberg13928972013-03-15 17:07:00 -05003164static void set_name_complete(struct hci_dev *hdev, u8 status)
3165{
3166 struct mgmt_cp_set_local_name *cp;
3167 struct pending_cmd *cmd;
3168
3169 BT_DBG("status 0x%02x", status);
3170
3171 hci_dev_lock(hdev);
3172
3173 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3174 if (!cmd)
3175 goto unlock;
3176
3177 cp = cmd->param;
3178
3179 if (status)
3180 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3181 mgmt_status(status));
3182 else
3183 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3184 cp, sizeof(*cp));
3185
3186 mgmt_pending_remove(cmd);
3187
3188unlock:
3189 hci_dev_unlock(hdev);
3190}
3191
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003192static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003193 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003194{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003195 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003196 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003197 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003198 int err;
3199
3200 BT_DBG("");
3201
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003202 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003203
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003204 /* If the old values are the same as the new ones just return a
3205 * direct command complete event.
3206 */
3207 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3208 !memcmp(hdev->short_name, cp->short_name,
3209 sizeof(hdev->short_name))) {
3210 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3211 data, len);
3212 goto failed;
3213 }
3214
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003215 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003216
Johan Hedbergb5235a62012-02-21 14:32:24 +02003217 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003218 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003219
3220 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003222 if (err < 0)
3223 goto failed;
3224
3225 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003226 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003227
Johan Hedbergb5235a62012-02-21 14:32:24 +02003228 goto failed;
3229 }
3230
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003231 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003232 if (!cmd) {
3233 err = -ENOMEM;
3234 goto failed;
3235 }
3236
Johan Hedberg13928972013-03-15 17:07:00 -05003237 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3238
Johan Hedberg890ea892013-03-15 17:06:52 -05003239 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003240
3241 if (lmp_bredr_capable(hdev)) {
3242 update_name(&req);
3243 update_eir(&req);
3244 }
3245
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003246 /* The name is stored in the scan response data and so
3247 * no need to udpate the advertising data here.
3248 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003249 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003250 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003251
Johan Hedberg13928972013-03-15 17:07:00 -05003252 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003253 if (err < 0)
3254 mgmt_pending_remove(cmd);
3255
3256failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003257 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003258 return err;
3259}
3260
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003261static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003262 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003263{
Szymon Jancc35938b2011-03-22 13:12:21 +01003264 struct pending_cmd *cmd;
3265 int err;
3266
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003267 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003268
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003269 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003270
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003271 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003272 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003273 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003274 goto unlock;
3275 }
3276
Andre Guedes9a1a1992012-07-24 15:03:48 -03003277 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003278 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003279 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003280 goto unlock;
3281 }
3282
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003283 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003284 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003285 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003286 goto unlock;
3287 }
3288
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003289 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003290 if (!cmd) {
3291 err = -ENOMEM;
3292 goto unlock;
3293 }
3294
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003295 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3296 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3297 0, NULL);
3298 else
3299 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3300
Szymon Jancc35938b2011-03-22 13:12:21 +01003301 if (err < 0)
3302 mgmt_pending_remove(cmd);
3303
3304unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003305 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003306 return err;
3307}
3308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003309static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003310 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003311{
Szymon Janc2763eda2011-03-22 13:12:22 +01003312 int err;
3313
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003314 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003315
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003316 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003317
Marcel Holtmannec109112014-01-10 02:07:30 -08003318 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3319 struct mgmt_cp_add_remote_oob_data *cp = data;
3320 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003321
Marcel Holtmannec109112014-01-10 02:07:30 -08003322 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3323 cp->hash, cp->randomizer);
3324 if (err < 0)
3325 status = MGMT_STATUS_FAILED;
3326 else
3327 status = MGMT_STATUS_SUCCESS;
3328
3329 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3330 status, &cp->addr, sizeof(cp->addr));
3331 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3332 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3333 u8 status;
3334
3335 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3336 cp->hash192,
3337 cp->randomizer192,
3338 cp->hash256,
3339 cp->randomizer256);
3340 if (err < 0)
3341 status = MGMT_STATUS_FAILED;
3342 else
3343 status = MGMT_STATUS_SUCCESS;
3344
3345 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3346 status, &cp->addr, sizeof(cp->addr));
3347 } else {
3348 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3349 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3350 MGMT_STATUS_INVALID_PARAMS);
3351 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003352
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003353 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003354 return err;
3355}
3356
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003357static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003358 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003359{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003360 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003361 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003362 int err;
3363
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003364 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003365
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003366 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003367
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003368 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003369 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003370 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003371 else
Szymon Janca6785be2012-12-13 15:11:21 +01003372 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003373
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003374 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003375 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003376
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003377 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003378 return err;
3379}
3380
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003381static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3382{
3383 struct pending_cmd *cmd;
3384 u8 type;
3385 int err;
3386
3387 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3388
3389 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3390 if (!cmd)
3391 return -ENOENT;
3392
3393 type = hdev->discovery.type;
3394
3395 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3396 &type, sizeof(type));
3397 mgmt_pending_remove(cmd);
3398
3399 return err;
3400}
3401
Andre Guedes7c307722013-04-30 15:29:28 -03003402static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3403{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003404 unsigned long timeout = 0;
3405
Andre Guedes7c307722013-04-30 15:29:28 -03003406 BT_DBG("status %d", status);
3407
3408 if (status) {
3409 hci_dev_lock(hdev);
3410 mgmt_start_discovery_failed(hdev, status);
3411 hci_dev_unlock(hdev);
3412 return;
3413 }
3414
3415 hci_dev_lock(hdev);
3416 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3417 hci_dev_unlock(hdev);
3418
3419 switch (hdev->discovery.type) {
3420 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003421 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003422 break;
3423
3424 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003425 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003426 break;
3427
3428 case DISCOV_TYPE_BREDR:
3429 break;
3430
3431 default:
3432 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3433 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003434
3435 if (!timeout)
3436 return;
3437
3438 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003439}
3440
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003441static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003442 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003443{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003444 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003445 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003446 struct hci_cp_le_set_scan_param param_cp;
3447 struct hci_cp_le_set_scan_enable enable_cp;
3448 struct hci_cp_inquiry inq_cp;
3449 struct hci_request req;
3450 /* General inquiry access code (GIAC) */
3451 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003452 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003453 int err;
3454
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003455 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003456
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003457 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003458
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003459 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003460 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003461 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003462 goto failed;
3463 }
3464
Andre Guedes642be6c2012-03-21 00:03:37 -03003465 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3466 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3467 MGMT_STATUS_BUSY);
3468 goto failed;
3469 }
3470
Johan Hedbergff9ef572012-01-04 14:23:45 +02003471 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003472 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003473 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003474 goto failed;
3475 }
3476
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003477 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003478 if (!cmd) {
3479 err = -ENOMEM;
3480 goto failed;
3481 }
3482
Andre Guedes4aab14e2012-02-17 20:39:36 -03003483 hdev->discovery.type = cp->type;
3484
Andre Guedes7c307722013-04-30 15:29:28 -03003485 hci_req_init(&req, hdev);
3486
Andre Guedes4aab14e2012-02-17 20:39:36 -03003487 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003488 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003489 status = mgmt_bredr_support(hdev);
3490 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003491 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003492 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003493 mgmt_pending_remove(cmd);
3494 goto failed;
3495 }
3496
Andre Guedes7c307722013-04-30 15:29:28 -03003497 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3498 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3499 MGMT_STATUS_BUSY);
3500 mgmt_pending_remove(cmd);
3501 goto failed;
3502 }
3503
3504 hci_inquiry_cache_flush(hdev);
3505
3506 memset(&inq_cp, 0, sizeof(inq_cp));
3507 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003508 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003509 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003510 break;
3511
3512 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003513 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003514 status = mgmt_le_support(hdev);
3515 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003516 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003517 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003518 mgmt_pending_remove(cmd);
3519 goto failed;
3520 }
3521
Andre Guedes7c307722013-04-30 15:29:28 -03003522 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003523 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003524 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3525 MGMT_STATUS_NOT_SUPPORTED);
3526 mgmt_pending_remove(cmd);
3527 goto failed;
3528 }
3529
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003530 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003531 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3532 MGMT_STATUS_REJECTED);
3533 mgmt_pending_remove(cmd);
3534 goto failed;
3535 }
3536
Andre Guedesc54c3862014-02-26 20:21:50 -03003537 /* If controller is scanning, it means the background scanning
3538 * is running. Thus, we should temporarily stop it in order to
3539 * set the discovery scanning parameters.
3540 */
3541 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3542 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003543
3544 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003545
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003546 /* All active scans will be done with either a resolvable
3547 * private address (when privacy feature has been enabled)
3548 * or unresolvable private address.
3549 */
3550 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003551 if (err < 0) {
3552 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3553 MGMT_STATUS_FAILED);
3554 mgmt_pending_remove(cmd);
3555 goto failed;
3556 }
3557
Andre Guedes7c307722013-04-30 15:29:28 -03003558 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003559 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3560 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003561 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003562 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3563 &param_cp);
3564
3565 memset(&enable_cp, 0, sizeof(enable_cp));
3566 enable_cp.enable = LE_SCAN_ENABLE;
3567 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3568 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3569 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003570 break;
3571
Andre Guedesf39799f2012-02-17 20:39:35 -03003572 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003573 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3574 MGMT_STATUS_INVALID_PARAMS);
3575 mgmt_pending_remove(cmd);
3576 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003577 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003578
Andre Guedes7c307722013-04-30 15:29:28 -03003579 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003580 if (err < 0)
3581 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003582 else
3583 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003584
3585failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003586 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003587 return err;
3588}
3589
Andre Guedes1183fdc2013-04-30 15:29:35 -03003590static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3591{
3592 struct pending_cmd *cmd;
3593 int err;
3594
3595 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3596 if (!cmd)
3597 return -ENOENT;
3598
3599 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3600 &hdev->discovery.type, sizeof(hdev->discovery.type));
3601 mgmt_pending_remove(cmd);
3602
3603 return err;
3604}
3605
Andre Guedes0e05bba2013-04-30 15:29:33 -03003606static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3607{
3608 BT_DBG("status %d", status);
3609
3610 hci_dev_lock(hdev);
3611
3612 if (status) {
3613 mgmt_stop_discovery_failed(hdev, status);
3614 goto unlock;
3615 }
3616
3617 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3618
3619unlock:
3620 hci_dev_unlock(hdev);
3621}
3622
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003623static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003624 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003625{
Johan Hedbergd9306502012-02-20 23:25:18 +02003626 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003627 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003628 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003629 int err;
3630
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003631 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003632
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003633 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003634
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003635 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003636 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003637 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3638 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003639 goto unlock;
3640 }
3641
3642 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003643 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003644 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3645 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003646 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003647 }
3648
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003649 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003650 if (!cmd) {
3651 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003652 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003653 }
3654
Andre Guedes0e05bba2013-04-30 15:29:33 -03003655 hci_req_init(&req, hdev);
3656
Johan Hedberg21a60d32014-06-10 14:05:58 +03003657 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003658
Johan Hedberg21a60d32014-06-10 14:05:58 +03003659 err = hci_req_run(&req, stop_discovery_complete);
3660 if (!err) {
3661 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003662 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003663 }
3664
Johan Hedberg21a60d32014-06-10 14:05:58 +03003665 mgmt_pending_remove(cmd);
3666
3667 /* If no HCI commands were sent we're done */
3668 if (err == -ENODATA) {
3669 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3670 &mgmt_cp->type, sizeof(mgmt_cp->type));
3671 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3672 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003673
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003674unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003675 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003676 return err;
3677}
3678
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003679static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003680 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003681{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003682 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003683 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003684 int err;
3685
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003686 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003687
Johan Hedberg561aafb2012-01-04 13:31:59 +02003688 hci_dev_lock(hdev);
3689
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003690 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003691 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3692 MGMT_STATUS_FAILED, &cp->addr,
3693 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003694 goto failed;
3695 }
3696
Johan Hedberga198e7b2012-02-17 14:27:06 +02003697 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003698 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003699 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3700 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3701 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003702 goto failed;
3703 }
3704
3705 if (cp->name_known) {
3706 e->name_state = NAME_KNOWN;
3707 list_del(&e->list);
3708 } else {
3709 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003710 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003711 }
3712
Johan Hedberge3846622013-01-09 15:29:33 +02003713 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3714 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003715
3716failed:
3717 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003718 return err;
3719}
3720
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003721static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003722 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003723{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003724 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003725 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003726 int err;
3727
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003728 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003729
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003730 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003731 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3732 MGMT_STATUS_INVALID_PARAMS,
3733 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003734
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003735 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003736
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003737 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003738 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003739 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003740 else
Szymon Janca6785be2012-12-13 15:11:21 +01003741 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003742
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003743 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003744 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003745
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003746 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003747
3748 return err;
3749}
3750
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003751static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003752 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003753{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003754 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003755 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003756 int err;
3757
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003758 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003759
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003760 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003761 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3762 MGMT_STATUS_INVALID_PARAMS,
3763 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003764
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003765 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003766
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003767 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003768 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003769 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003770 else
Szymon Janca6785be2012-12-13 15:11:21 +01003771 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003772
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003773 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003774 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003775
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003776 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003777
3778 return err;
3779}
3780
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003781static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3782 u16 len)
3783{
3784 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003785 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003786 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003787 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003788
3789 BT_DBG("%s", hdev->name);
3790
Szymon Jancc72d4b82012-03-16 16:02:57 +01003791 source = __le16_to_cpu(cp->source);
3792
3793 if (source > 0x0002)
3794 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3795 MGMT_STATUS_INVALID_PARAMS);
3796
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003797 hci_dev_lock(hdev);
3798
Szymon Jancc72d4b82012-03-16 16:02:57 +01003799 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003800 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3801 hdev->devid_product = __le16_to_cpu(cp->product);
3802 hdev->devid_version = __le16_to_cpu(cp->version);
3803
3804 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3805
Johan Hedberg890ea892013-03-15 17:06:52 -05003806 hci_req_init(&req, hdev);
3807 update_eir(&req);
3808 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003809
3810 hci_dev_unlock(hdev);
3811
3812 return err;
3813}
3814
Johan Hedberg4375f102013-09-25 13:26:10 +03003815static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3816{
3817 struct cmd_lookup match = { NULL, hdev };
3818
3819 if (status) {
3820 u8 mgmt_err = mgmt_status(status);
3821
3822 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3823 cmd_status_rsp, &mgmt_err);
3824 return;
3825 }
3826
3827 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3828 &match);
3829
3830 new_settings(hdev, match.sk);
3831
3832 if (match.sk)
3833 sock_put(match.sk);
3834}
3835
Marcel Holtmann21b51872013-10-10 09:47:53 -07003836static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3837 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003838{
3839 struct mgmt_mode *cp = data;
3840 struct pending_cmd *cmd;
3841 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003842 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003843 int err;
3844
3845 BT_DBG("request for %s", hdev->name);
3846
Johan Hedberge6fe7982013-10-02 15:45:22 +03003847 status = mgmt_le_support(hdev);
3848 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003849 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003850 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003851
3852 if (cp->val != 0x00 && cp->val != 0x01)
3853 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3854 MGMT_STATUS_INVALID_PARAMS);
3855
3856 hci_dev_lock(hdev);
3857
3858 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003859 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003860
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003861 /* The following conditions are ones which mean that we should
3862 * not do any HCI communication but directly send a mgmt
3863 * response to user space (after toggling the flag if
3864 * necessary).
3865 */
3866 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003867 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003868 bool changed = false;
3869
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003870 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3871 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003872 changed = true;
3873 }
3874
3875 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3876 if (err < 0)
3877 goto unlock;
3878
3879 if (changed)
3880 err = new_settings(hdev, sk);
3881
3882 goto unlock;
3883 }
3884
3885 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3886 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3888 MGMT_STATUS_BUSY);
3889 goto unlock;
3890 }
3891
3892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3893 if (!cmd) {
3894 err = -ENOMEM;
3895 goto unlock;
3896 }
3897
3898 hci_req_init(&req, hdev);
3899
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003900 if (val)
3901 enable_advertising(&req);
3902 else
3903 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003904
3905 err = hci_req_run(&req, set_advertising_complete);
3906 if (err < 0)
3907 mgmt_pending_remove(cmd);
3908
3909unlock:
3910 hci_dev_unlock(hdev);
3911 return err;
3912}
3913
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003914static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3915 void *data, u16 len)
3916{
3917 struct mgmt_cp_set_static_address *cp = data;
3918 int err;
3919
3920 BT_DBG("%s", hdev->name);
3921
Marcel Holtmann62af4442013-10-02 22:10:32 -07003922 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003923 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003924 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003925
3926 if (hdev_is_powered(hdev))
3927 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3928 MGMT_STATUS_REJECTED);
3929
3930 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3931 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3932 return cmd_status(sk, hdev->id,
3933 MGMT_OP_SET_STATIC_ADDRESS,
3934 MGMT_STATUS_INVALID_PARAMS);
3935
3936 /* Two most significant bits shall be set */
3937 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3938 return cmd_status(sk, hdev->id,
3939 MGMT_OP_SET_STATIC_ADDRESS,
3940 MGMT_STATUS_INVALID_PARAMS);
3941 }
3942
3943 hci_dev_lock(hdev);
3944
3945 bacpy(&hdev->static_addr, &cp->bdaddr);
3946
3947 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3948
3949 hci_dev_unlock(hdev);
3950
3951 return err;
3952}
3953
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003954static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3955 void *data, u16 len)
3956{
3957 struct mgmt_cp_set_scan_params *cp = data;
3958 __u16 interval, window;
3959 int err;
3960
3961 BT_DBG("%s", hdev->name);
3962
3963 if (!lmp_le_capable(hdev))
3964 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3965 MGMT_STATUS_NOT_SUPPORTED);
3966
3967 interval = __le16_to_cpu(cp->interval);
3968
3969 if (interval < 0x0004 || interval > 0x4000)
3970 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3971 MGMT_STATUS_INVALID_PARAMS);
3972
3973 window = __le16_to_cpu(cp->window);
3974
3975 if (window < 0x0004 || window > 0x4000)
3976 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3977 MGMT_STATUS_INVALID_PARAMS);
3978
Marcel Holtmann899e1072013-10-14 09:55:32 -07003979 if (window > interval)
3980 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3981 MGMT_STATUS_INVALID_PARAMS);
3982
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003983 hci_dev_lock(hdev);
3984
3985 hdev->le_scan_interval = interval;
3986 hdev->le_scan_window = window;
3987
3988 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3989
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003990 /* If background scan is running, restart it so new parameters are
3991 * loaded.
3992 */
3993 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
3994 hdev->discovery.state == DISCOVERY_STOPPED) {
3995 struct hci_request req;
3996
3997 hci_req_init(&req, hdev);
3998
3999 hci_req_add_le_scan_disable(&req);
4000 hci_req_add_le_passive_scan(&req);
4001
4002 hci_req_run(&req, NULL);
4003 }
4004
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004005 hci_dev_unlock(hdev);
4006
4007 return err;
4008}
4009
Johan Hedberg33e38b32013-03-15 17:07:05 -05004010static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4011{
4012 struct pending_cmd *cmd;
4013
4014 BT_DBG("status 0x%02x", status);
4015
4016 hci_dev_lock(hdev);
4017
4018 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4019 if (!cmd)
4020 goto unlock;
4021
4022 if (status) {
4023 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4024 mgmt_status(status));
4025 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004026 struct mgmt_mode *cp = cmd->param;
4027
4028 if (cp->val)
4029 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4030 else
4031 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4032
Johan Hedberg33e38b32013-03-15 17:07:05 -05004033 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4034 new_settings(hdev, cmd->sk);
4035 }
4036
4037 mgmt_pending_remove(cmd);
4038
4039unlock:
4040 hci_dev_unlock(hdev);
4041}
4042
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004043static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004044 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004045{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004046 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004047 struct pending_cmd *cmd;
4048 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004049 int err;
4050
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004051 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004052
Johan Hedberg56f87902013-10-02 13:43:13 +03004053 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4054 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004055 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4056 MGMT_STATUS_NOT_SUPPORTED);
4057
Johan Hedberga7e80f22013-01-09 16:05:19 +02004058 if (cp->val != 0x00 && cp->val != 0x01)
4059 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4060 MGMT_STATUS_INVALID_PARAMS);
4061
Johan Hedberg5400c042012-02-21 16:40:33 +02004062 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004063 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004064 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004065
4066 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004067 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004068 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004069
4070 hci_dev_lock(hdev);
4071
Johan Hedberg05cbf292013-03-15 17:07:07 -05004072 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4073 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4074 MGMT_STATUS_BUSY);
4075 goto unlock;
4076 }
4077
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004078 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4079 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4080 hdev);
4081 goto unlock;
4082 }
4083
Johan Hedberg33e38b32013-03-15 17:07:05 -05004084 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4085 data, len);
4086 if (!cmd) {
4087 err = -ENOMEM;
4088 goto unlock;
4089 }
4090
4091 hci_req_init(&req, hdev);
4092
Johan Hedberg406d7802013-03-15 17:07:09 -05004093 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004094
4095 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004096 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004097 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004098 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004099 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004100 }
4101
Johan Hedberg33e38b32013-03-15 17:07:05 -05004102unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004103 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004104
Antti Julkuf6422ec2011-06-22 13:11:56 +03004105 return err;
4106}
4107
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004108static void set_bredr_scan(struct hci_request *req)
4109{
4110 struct hci_dev *hdev = req->hdev;
4111 u8 scan = 0;
4112
4113 /* Ensure that fast connectable is disabled. This function will
4114 * not do anything if the page scan parameters are already what
4115 * they should be.
4116 */
4117 write_fast_connectable(req, false);
4118
4119 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4120 scan |= SCAN_PAGE;
4121 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4122 scan |= SCAN_INQUIRY;
4123
4124 if (scan)
4125 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4126}
4127
Johan Hedberg0663ca22013-10-02 13:43:14 +03004128static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4129{
4130 struct pending_cmd *cmd;
4131
4132 BT_DBG("status 0x%02x", status);
4133
4134 hci_dev_lock(hdev);
4135
4136 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4137 if (!cmd)
4138 goto unlock;
4139
4140 if (status) {
4141 u8 mgmt_err = mgmt_status(status);
4142
4143 /* We need to restore the flag if related HCI commands
4144 * failed.
4145 */
4146 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4147
4148 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4149 } else {
4150 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4151 new_settings(hdev, cmd->sk);
4152 }
4153
4154 mgmt_pending_remove(cmd);
4155
4156unlock:
4157 hci_dev_unlock(hdev);
4158}
4159
4160static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4161{
4162 struct mgmt_mode *cp = data;
4163 struct pending_cmd *cmd;
4164 struct hci_request req;
4165 int err;
4166
4167 BT_DBG("request for %s", hdev->name);
4168
4169 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4170 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4171 MGMT_STATUS_NOT_SUPPORTED);
4172
4173 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4174 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4175 MGMT_STATUS_REJECTED);
4176
4177 if (cp->val != 0x00 && cp->val != 0x01)
4178 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4179 MGMT_STATUS_INVALID_PARAMS);
4180
4181 hci_dev_lock(hdev);
4182
4183 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4184 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4185 goto unlock;
4186 }
4187
4188 if (!hdev_is_powered(hdev)) {
4189 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004190 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4191 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4192 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4193 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4194 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4195 }
4196
4197 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4198
4199 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4200 if (err < 0)
4201 goto unlock;
4202
4203 err = new_settings(hdev, sk);
4204 goto unlock;
4205 }
4206
4207 /* Reject disabling when powered on */
4208 if (!cp->val) {
4209 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4210 MGMT_STATUS_REJECTED);
4211 goto unlock;
4212 }
4213
4214 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4215 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4216 MGMT_STATUS_BUSY);
4217 goto unlock;
4218 }
4219
4220 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4221 if (!cmd) {
4222 err = -ENOMEM;
4223 goto unlock;
4224 }
4225
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004226 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004227 * generates the correct flags.
4228 */
4229 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4230
4231 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004232
4233 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4234 set_bredr_scan(&req);
4235
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004236 /* Since only the advertising data flags will change, there
4237 * is no need to update the scan response data.
4238 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004239 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004240
Johan Hedberg0663ca22013-10-02 13:43:14 +03004241 err = hci_req_run(&req, set_bredr_complete);
4242 if (err < 0)
4243 mgmt_pending_remove(cmd);
4244
4245unlock:
4246 hci_dev_unlock(hdev);
4247 return err;
4248}
4249
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004250static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4251 void *data, u16 len)
4252{
4253 struct mgmt_mode *cp = data;
4254 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004255 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004256 int err;
4257
4258 BT_DBG("request for %s", hdev->name);
4259
4260 status = mgmt_bredr_support(hdev);
4261 if (status)
4262 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4263 status);
4264
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004265 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004266 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004267 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4268 MGMT_STATUS_NOT_SUPPORTED);
4269
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004270 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004271 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4272 MGMT_STATUS_INVALID_PARAMS);
4273
4274 hci_dev_lock(hdev);
4275
4276 if (!hdev_is_powered(hdev)) {
4277 bool changed;
4278
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004279 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004280 changed = !test_and_set_bit(HCI_SC_ENABLED,
4281 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004282 if (cp->val == 0x02)
4283 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4284 else
4285 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4286 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004287 changed = test_and_clear_bit(HCI_SC_ENABLED,
4288 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004289 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4290 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004291
4292 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4293 if (err < 0)
4294 goto failed;
4295
4296 if (changed)
4297 err = new_settings(hdev, sk);
4298
4299 goto failed;
4300 }
4301
4302 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4303 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4304 MGMT_STATUS_BUSY);
4305 goto failed;
4306 }
4307
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004308 val = !!cp->val;
4309
4310 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4311 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004312 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4313 goto failed;
4314 }
4315
4316 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4317 if (!cmd) {
4318 err = -ENOMEM;
4319 goto failed;
4320 }
4321
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004322 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004323 if (err < 0) {
4324 mgmt_pending_remove(cmd);
4325 goto failed;
4326 }
4327
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004328 if (cp->val == 0x02)
4329 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4330 else
4331 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4332
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004333failed:
4334 hci_dev_unlock(hdev);
4335 return err;
4336}
4337
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004338static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4339 void *data, u16 len)
4340{
4341 struct mgmt_mode *cp = data;
4342 bool changed;
4343 int err;
4344
4345 BT_DBG("request for %s", hdev->name);
4346
4347 if (cp->val != 0x00 && cp->val != 0x01)
4348 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4349 MGMT_STATUS_INVALID_PARAMS);
4350
4351 hci_dev_lock(hdev);
4352
4353 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004354 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4355 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004356 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004357 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4358 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004359
4360 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4361 if (err < 0)
4362 goto unlock;
4363
4364 if (changed)
4365 err = new_settings(hdev, sk);
4366
4367unlock:
4368 hci_dev_unlock(hdev);
4369 return err;
4370}
4371
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004372static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4373 u16 len)
4374{
4375 struct mgmt_cp_set_privacy *cp = cp_data;
4376 bool changed;
4377 int err;
4378
4379 BT_DBG("request for %s", hdev->name);
4380
4381 if (!lmp_le_capable(hdev))
4382 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4383 MGMT_STATUS_NOT_SUPPORTED);
4384
4385 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4386 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4387 MGMT_STATUS_INVALID_PARAMS);
4388
4389 if (hdev_is_powered(hdev))
4390 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4391 MGMT_STATUS_REJECTED);
4392
4393 hci_dev_lock(hdev);
4394
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004395 /* If user space supports this command it is also expected to
4396 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4397 */
4398 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4399
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004400 if (cp->privacy) {
4401 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4402 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4403 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4404 } else {
4405 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4406 memset(hdev->irk, 0, sizeof(hdev->irk));
4407 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4408 }
4409
4410 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4411 if (err < 0)
4412 goto unlock;
4413
4414 if (changed)
4415 err = new_settings(hdev, sk);
4416
4417unlock:
4418 hci_dev_unlock(hdev);
4419 return err;
4420}
4421
Johan Hedberg41edf162014-02-18 10:19:35 +02004422static bool irk_is_valid(struct mgmt_irk_info *irk)
4423{
4424 switch (irk->addr.type) {
4425 case BDADDR_LE_PUBLIC:
4426 return true;
4427
4428 case BDADDR_LE_RANDOM:
4429 /* Two most significant bits shall be set */
4430 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4431 return false;
4432 return true;
4433 }
4434
4435 return false;
4436}
4437
4438static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4439 u16 len)
4440{
4441 struct mgmt_cp_load_irks *cp = cp_data;
4442 u16 irk_count, expected_len;
4443 int i, err;
4444
4445 BT_DBG("request for %s", hdev->name);
4446
4447 if (!lmp_le_capable(hdev))
4448 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4449 MGMT_STATUS_NOT_SUPPORTED);
4450
4451 irk_count = __le16_to_cpu(cp->irk_count);
4452
4453 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4454 if (expected_len != len) {
4455 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004456 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004457 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4458 MGMT_STATUS_INVALID_PARAMS);
4459 }
4460
4461 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4462
4463 for (i = 0; i < irk_count; i++) {
4464 struct mgmt_irk_info *key = &cp->irks[i];
4465
4466 if (!irk_is_valid(key))
4467 return cmd_status(sk, hdev->id,
4468 MGMT_OP_LOAD_IRKS,
4469 MGMT_STATUS_INVALID_PARAMS);
4470 }
4471
4472 hci_dev_lock(hdev);
4473
4474 hci_smp_irks_clear(hdev);
4475
4476 for (i = 0; i < irk_count; i++) {
4477 struct mgmt_irk_info *irk = &cp->irks[i];
4478 u8 addr_type;
4479
4480 if (irk->addr.type == BDADDR_LE_PUBLIC)
4481 addr_type = ADDR_LE_DEV_PUBLIC;
4482 else
4483 addr_type = ADDR_LE_DEV_RANDOM;
4484
4485 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4486 BDADDR_ANY);
4487 }
4488
4489 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4490
4491 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4492
4493 hci_dev_unlock(hdev);
4494
4495 return err;
4496}
4497
Johan Hedberg3f706b72013-01-20 14:27:16 +02004498static bool ltk_is_valid(struct mgmt_ltk_info *key)
4499{
4500 if (key->master != 0x00 && key->master != 0x01)
4501 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004502
4503 switch (key->addr.type) {
4504 case BDADDR_LE_PUBLIC:
4505 return true;
4506
4507 case BDADDR_LE_RANDOM:
4508 /* Two most significant bits shall be set */
4509 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4510 return false;
4511 return true;
4512 }
4513
4514 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004515}
4516
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004517static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004518 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004519{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004520 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4521 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004522 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004523
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004524 BT_DBG("request for %s", hdev->name);
4525
4526 if (!lmp_le_capable(hdev))
4527 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4528 MGMT_STATUS_NOT_SUPPORTED);
4529
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004530 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004531
4532 expected_len = sizeof(*cp) + key_count *
4533 sizeof(struct mgmt_ltk_info);
4534 if (expected_len != len) {
4535 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004536 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004537 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004538 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004539 }
4540
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004541 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004542
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004543 for (i = 0; i < key_count; i++) {
4544 struct mgmt_ltk_info *key = &cp->keys[i];
4545
Johan Hedberg3f706b72013-01-20 14:27:16 +02004546 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004547 return cmd_status(sk, hdev->id,
4548 MGMT_OP_LOAD_LONG_TERM_KEYS,
4549 MGMT_STATUS_INVALID_PARAMS);
4550 }
4551
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004552 hci_dev_lock(hdev);
4553
4554 hci_smp_ltks_clear(hdev);
4555
4556 for (i = 0; i < key_count; i++) {
4557 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004558 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004559
4560 if (key->addr.type == BDADDR_LE_PUBLIC)
4561 addr_type = ADDR_LE_DEV_PUBLIC;
4562 else
4563 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004564
4565 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004566 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004567 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004568 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004569
Johan Hedberg61b43352014-05-29 19:36:53 +03004570 switch (key->type) {
4571 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004572 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004573 break;
4574 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004575 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004576 break;
4577 default:
4578 continue;
4579 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004580
Johan Hedberg35d70272014-02-19 14:57:47 +02004581 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004582 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004583 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004584 }
4585
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004586 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4587 NULL, 0);
4588
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004589 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004590
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004591 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004592}
4593
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004594struct cmd_conn_lookup {
4595 struct hci_conn *conn;
4596 bool valid_tx_power;
4597 u8 mgmt_status;
4598};
4599
4600static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4601{
4602 struct cmd_conn_lookup *match = data;
4603 struct mgmt_cp_get_conn_info *cp;
4604 struct mgmt_rp_get_conn_info rp;
4605 struct hci_conn *conn = cmd->user_data;
4606
4607 if (conn != match->conn)
4608 return;
4609
4610 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4611
4612 memset(&rp, 0, sizeof(rp));
4613 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4614 rp.addr.type = cp->addr.type;
4615
4616 if (!match->mgmt_status) {
4617 rp.rssi = conn->rssi;
4618
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004619 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004620 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004621 rp.max_tx_power = conn->max_tx_power;
4622 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004623 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004624 rp.max_tx_power = HCI_TX_POWER_INVALID;
4625 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004626 }
4627
4628 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4629 match->mgmt_status, &rp, sizeof(rp));
4630
4631 hci_conn_drop(conn);
4632
4633 mgmt_pending_remove(cmd);
4634}
4635
4636static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4637{
4638 struct hci_cp_read_rssi *cp;
4639 struct hci_conn *conn;
4640 struct cmd_conn_lookup match;
4641 u16 handle;
4642
4643 BT_DBG("status 0x%02x", status);
4644
4645 hci_dev_lock(hdev);
4646
4647 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004648 * otherwise we assume it's not valid. At the moment we assume that
4649 * either both or none of current and max values are valid to keep code
4650 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004651 */
4652 match.valid_tx_power = !status;
4653
4654 /* Commands sent in request are either Read RSSI or Read Transmit Power
4655 * Level so we check which one was last sent to retrieve connection
4656 * handle. Both commands have handle as first parameter so it's safe to
4657 * cast data on the same command struct.
4658 *
4659 * First command sent is always Read RSSI and we fail only if it fails.
4660 * In other case we simply override error to indicate success as we
4661 * already remembered if TX power value is actually valid.
4662 */
4663 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4664 if (!cp) {
4665 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4666 status = 0;
4667 }
4668
4669 if (!cp) {
4670 BT_ERR("invalid sent_cmd in response");
4671 goto unlock;
4672 }
4673
4674 handle = __le16_to_cpu(cp->handle);
4675 conn = hci_conn_hash_lookup_handle(hdev, handle);
4676 if (!conn) {
4677 BT_ERR("unknown handle (%d) in response", handle);
4678 goto unlock;
4679 }
4680
4681 match.conn = conn;
4682 match.mgmt_status = mgmt_status(status);
4683
4684 /* Cache refresh is complete, now reply for mgmt request for given
4685 * connection only.
4686 */
4687 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4688 get_conn_info_complete, &match);
4689
4690unlock:
4691 hci_dev_unlock(hdev);
4692}
4693
4694static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4695 u16 len)
4696{
4697 struct mgmt_cp_get_conn_info *cp = data;
4698 struct mgmt_rp_get_conn_info rp;
4699 struct hci_conn *conn;
4700 unsigned long conn_info_age;
4701 int err = 0;
4702
4703 BT_DBG("%s", hdev->name);
4704
4705 memset(&rp, 0, sizeof(rp));
4706 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4707 rp.addr.type = cp->addr.type;
4708
4709 if (!bdaddr_type_is_valid(cp->addr.type))
4710 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4711 MGMT_STATUS_INVALID_PARAMS,
4712 &rp, sizeof(rp));
4713
4714 hci_dev_lock(hdev);
4715
4716 if (!hdev_is_powered(hdev)) {
4717 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4718 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4719 goto unlock;
4720 }
4721
4722 if (cp->addr.type == BDADDR_BREDR)
4723 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4724 &cp->addr.bdaddr);
4725 else
4726 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4727
4728 if (!conn || conn->state != BT_CONNECTED) {
4729 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4730 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4731 goto unlock;
4732 }
4733
4734 /* To avoid client trying to guess when to poll again for information we
4735 * calculate conn info age as random value between min/max set in hdev.
4736 */
4737 conn_info_age = hdev->conn_info_min_age +
4738 prandom_u32_max(hdev->conn_info_max_age -
4739 hdev->conn_info_min_age);
4740
4741 /* Query controller to refresh cached values if they are too old or were
4742 * never read.
4743 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004744 if (time_after(jiffies, conn->conn_info_timestamp +
4745 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004746 !conn->conn_info_timestamp) {
4747 struct hci_request req;
4748 struct hci_cp_read_tx_power req_txp_cp;
4749 struct hci_cp_read_rssi req_rssi_cp;
4750 struct pending_cmd *cmd;
4751
4752 hci_req_init(&req, hdev);
4753 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4754 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4755 &req_rssi_cp);
4756
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004757 /* For LE links TX power does not change thus we don't need to
4758 * query for it once value is known.
4759 */
4760 if (!bdaddr_type_is_le(cp->addr.type) ||
4761 conn->tx_power == HCI_TX_POWER_INVALID) {
4762 req_txp_cp.handle = cpu_to_le16(conn->handle);
4763 req_txp_cp.type = 0x00;
4764 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4765 sizeof(req_txp_cp), &req_txp_cp);
4766 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004767
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004768 /* Max TX power needs to be read only once per connection */
4769 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4770 req_txp_cp.handle = cpu_to_le16(conn->handle);
4771 req_txp_cp.type = 0x01;
4772 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4773 sizeof(req_txp_cp), &req_txp_cp);
4774 }
4775
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004776 err = hci_req_run(&req, conn_info_refresh_complete);
4777 if (err < 0)
4778 goto unlock;
4779
4780 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4781 data, len);
4782 if (!cmd) {
4783 err = -ENOMEM;
4784 goto unlock;
4785 }
4786
4787 hci_conn_hold(conn);
4788 cmd->user_data = conn;
4789
4790 conn->conn_info_timestamp = jiffies;
4791 } else {
4792 /* Cache is valid, just reply with values cached in hci_conn */
4793 rp.rssi = conn->rssi;
4794 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004795 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004796
4797 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4798 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4799 }
4800
4801unlock:
4802 hci_dev_unlock(hdev);
4803 return err;
4804}
4805
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004806static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004807 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4808 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004809 bool var_len;
4810 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004811} mgmt_handlers[] = {
4812 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004813 { read_version, false, MGMT_READ_VERSION_SIZE },
4814 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4815 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4816 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4817 { set_powered, false, MGMT_SETTING_SIZE },
4818 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4819 { set_connectable, false, MGMT_SETTING_SIZE },
4820 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4821 { set_pairable, false, MGMT_SETTING_SIZE },
4822 { set_link_security, false, MGMT_SETTING_SIZE },
4823 { set_ssp, false, MGMT_SETTING_SIZE },
4824 { set_hs, false, MGMT_SETTING_SIZE },
4825 { set_le, false, MGMT_SETTING_SIZE },
4826 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4827 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4828 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4829 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4830 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4831 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4832 { disconnect, false, MGMT_DISCONNECT_SIZE },
4833 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4834 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4835 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4836 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4837 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4838 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4839 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4840 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4841 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4842 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4843 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4844 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004845 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004846 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4847 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4848 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4849 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4850 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4851 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004852 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004853 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004854 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004855 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004856 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004857 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004858 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004859 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004860 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004861 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004862};
4863
4864
Johan Hedberg03811012010-12-08 00:21:06 +02004865int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4866{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004867 void *buf;
4868 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004869 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004870 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004871 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004872 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004873 int err;
4874
4875 BT_DBG("got %zu bytes", msglen);
4876
4877 if (msglen < sizeof(*hdr))
4878 return -EINVAL;
4879
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004880 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004881 if (!buf)
4882 return -ENOMEM;
4883
4884 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4885 err = -EFAULT;
4886 goto done;
4887 }
4888
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004889 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004890 opcode = __le16_to_cpu(hdr->opcode);
4891 index = __le16_to_cpu(hdr->index);
4892 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004893
4894 if (len != msglen - sizeof(*hdr)) {
4895 err = -EINVAL;
4896 goto done;
4897 }
4898
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004899 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004900 hdev = hci_dev_get(index);
4901 if (!hdev) {
4902 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004903 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004904 goto done;
4905 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004906
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004907 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4908 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004909 err = cmd_status(sk, index, opcode,
4910 MGMT_STATUS_INVALID_INDEX);
4911 goto done;
4912 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004913 }
4914
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004915 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004916 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004917 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004918 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004919 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004920 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004921 }
4922
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004923 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004924 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004925 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004926 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004927 goto done;
4928 }
4929
Johan Hedbergbe22b542012-03-01 22:24:41 +02004930 handler = &mgmt_handlers[opcode];
4931
4932 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004933 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004934 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004935 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004936 goto done;
4937 }
4938
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004939 if (hdev)
4940 mgmt_init_hdev(sk, hdev);
4941
4942 cp = buf + sizeof(*hdr);
4943
Johan Hedbergbe22b542012-03-01 22:24:41 +02004944 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004945 if (err < 0)
4946 goto done;
4947
Johan Hedberg03811012010-12-08 00:21:06 +02004948 err = msglen;
4949
4950done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004951 if (hdev)
4952 hci_dev_put(hdev);
4953
Johan Hedberg03811012010-12-08 00:21:06 +02004954 kfree(buf);
4955 return err;
4956}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004957
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004958void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004959{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004960 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004961 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004962
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004963 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004964}
4965
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004966void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004967{
Johan Hedberg5f159032012-03-02 03:13:19 +02004968 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004969
Marcel Holtmann1514b892013-10-06 08:25:01 -07004970 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004971 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004972
Johan Hedberg744cf192011-11-08 20:40:14 +02004973 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004974
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004975 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004976}
4977
Andre Guedes6046dc32014-02-26 20:21:51 -03004978/* This function requires the caller holds hdev->lock */
4979static void restart_le_auto_conns(struct hci_dev *hdev)
4980{
4981 struct hci_conn_params *p;
4982
4983 list_for_each_entry(p, &hdev->le_conn_params, list) {
4984 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4985 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4986 }
4987}
4988
Johan Hedberg229ab392013-03-15 17:06:53 -05004989static void powered_complete(struct hci_dev *hdev, u8 status)
4990{
4991 struct cmd_lookup match = { NULL, hdev };
4992
4993 BT_DBG("status 0x%02x", status);
4994
4995 hci_dev_lock(hdev);
4996
Andre Guedes6046dc32014-02-26 20:21:51 -03004997 restart_le_auto_conns(hdev);
4998
Johan Hedberg229ab392013-03-15 17:06:53 -05004999 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5000
5001 new_settings(hdev, match.sk);
5002
5003 hci_dev_unlock(hdev);
5004
5005 if (match.sk)
5006 sock_put(match.sk);
5007}
5008
Johan Hedberg70da6242013-03-15 17:06:51 -05005009static int powered_update_hci(struct hci_dev *hdev)
5010{
Johan Hedberg890ea892013-03-15 17:06:52 -05005011 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005012 u8 link_sec;
5013
Johan Hedberg890ea892013-03-15 17:06:52 -05005014 hci_req_init(&req, hdev);
5015
Johan Hedberg70da6242013-03-15 17:06:51 -05005016 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5017 !lmp_host_ssp_capable(hdev)) {
5018 u8 ssp = 1;
5019
Johan Hedberg890ea892013-03-15 17:06:52 -05005020 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005021 }
5022
Johan Hedbergc73eee92013-04-19 18:35:21 +03005023 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5024 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005025 struct hci_cp_write_le_host_supported cp;
5026
5027 cp.le = 1;
5028 cp.simul = lmp_le_br_capable(hdev);
5029
5030 /* Check first if we already have the right
5031 * host state (host features set)
5032 */
5033 if (cp.le != lmp_host_le_capable(hdev) ||
5034 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005035 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5036 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005037 }
5038
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005039 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005040 /* Make sure the controller has a good default for
5041 * advertising data. This also applies to the case
5042 * where BR/EDR was toggled during the AUTO_OFF phase.
5043 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005044 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005045 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005046 update_scan_rsp_data(&req);
5047 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005048
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005049 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5050 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005051 }
5052
Johan Hedberg70da6242013-03-15 17:06:51 -05005053 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5054 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005055 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5056 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005057
5058 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005059 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5060 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005061 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005062 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005063 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005064 }
5065
Johan Hedberg229ab392013-03-15 17:06:53 -05005066 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005067}
5068
Johan Hedberg744cf192011-11-08 20:40:14 +02005069int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005070{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005071 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005072 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5073 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005074 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005075
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005076 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5077 return 0;
5078
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005079 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005080 if (powered_update_hci(hdev) == 0)
5081 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005082
Johan Hedberg229ab392013-03-15 17:06:53 -05005083 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5084 &match);
5085 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005086 }
5087
Johan Hedberg229ab392013-03-15 17:06:53 -05005088 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5089 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5090
5091 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5092 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5093 zero_cod, sizeof(zero_cod), NULL);
5094
5095new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005096 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005097
5098 if (match.sk)
5099 sock_put(match.sk);
5100
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005101 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005102}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005103
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005104void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005105{
5106 struct pending_cmd *cmd;
5107 u8 status;
5108
5109 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5110 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005111 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005112
5113 if (err == -ERFKILL)
5114 status = MGMT_STATUS_RFKILLED;
5115 else
5116 status = MGMT_STATUS_FAILED;
5117
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005118 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005119
5120 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005121}
5122
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005123void mgmt_discoverable_timeout(struct hci_dev *hdev)
5124{
5125 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005126
5127 hci_dev_lock(hdev);
5128
5129 /* When discoverable timeout triggers, then just make sure
5130 * the limited discoverable flag is cleared. Even in the case
5131 * of a timeout triggered from general discoverable, it is
5132 * safe to unconditionally clear the flag.
5133 */
5134 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005135 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005136
5137 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005138 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5139 u8 scan = SCAN_PAGE;
5140 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5141 sizeof(scan), &scan);
5142 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005143 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005144 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005145 hci_req_run(&req, NULL);
5146
5147 hdev->discov_timeout = 0;
5148
Johan Hedberg9a43e252013-10-20 19:00:07 +03005149 new_settings(hdev, NULL);
5150
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005151 hci_dev_unlock(hdev);
5152}
5153
Marcel Holtmann86a75642013-10-15 06:33:54 -07005154void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005155{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005156 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005157
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005158 /* Nothing needed here if there's a pending command since that
5159 * commands request completion callback takes care of everything
5160 * necessary.
5161 */
5162 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005163 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005164
Johan Hedbergbd107992014-02-24 14:52:19 +02005165 /* Powering off may clear the scan mode - don't let that interfere */
5166 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5167 return;
5168
Johan Hedberg9a43e252013-10-20 19:00:07 +03005169 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005170 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005171 } else {
5172 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005173 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005174 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005175
Johan Hedberg9a43e252013-10-20 19:00:07 +03005176 if (changed) {
5177 struct hci_request req;
5178
5179 /* In case this change in discoverable was triggered by
5180 * a disabling of connectable there could be a need to
5181 * update the advertising flags.
5182 */
5183 hci_req_init(&req, hdev);
5184 update_adv_data(&req);
5185 hci_req_run(&req, NULL);
5186
Marcel Holtmann86a75642013-10-15 06:33:54 -07005187 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005188 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005189}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005190
Marcel Holtmanna3309162013-10-15 06:33:55 -07005191void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005192{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005193 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005194
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005195 /* Nothing needed here if there's a pending command since that
5196 * commands request completion callback takes care of everything
5197 * necessary.
5198 */
5199 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005200 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005201
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005202 /* Powering off may clear the scan mode - don't let that interfere */
5203 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5204 return;
5205
Marcel Holtmanna3309162013-10-15 06:33:55 -07005206 if (connectable)
5207 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5208 else
5209 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005210
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005211 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005212 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005213}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005214
Johan Hedberg778b2352014-02-24 14:52:17 +02005215void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5216{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005217 /* Powering off may stop advertising - don't let that interfere */
5218 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5219 return;
5220
Johan Hedberg778b2352014-02-24 14:52:17 +02005221 if (advertising)
5222 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5223 else
5224 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5225}
5226
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005227void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005228{
Johan Hedbergca69b792011-11-11 18:10:00 +02005229 u8 mgmt_err = mgmt_status(status);
5230
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005231 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005232 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005233 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005234
5235 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005236 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005237 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005238}
5239
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005240void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5241 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005242{
Johan Hedberg86742e12011-11-07 23:13:38 +02005243 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005244
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005245 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005246
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005247 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005248 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005249 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005250 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005251 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005252 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005253
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005254 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005255}
Johan Hedbergf7520542011-01-20 12:34:39 +02005256
Johan Hedbergd7b25452014-05-23 13:19:53 +03005257static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5258{
5259 if (ltk->authenticated)
5260 return MGMT_LTK_AUTHENTICATED;
5261
5262 return MGMT_LTK_UNAUTHENTICATED;
5263}
5264
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005265void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005266{
5267 struct mgmt_ev_new_long_term_key ev;
5268
5269 memset(&ev, 0, sizeof(ev));
5270
Marcel Holtmann5192d302014-02-19 17:11:58 -08005271 /* Devices using resolvable or non-resolvable random addresses
5272 * without providing an indentity resolving key don't require
5273 * to store long term keys. Their addresses will change the
5274 * next time around.
5275 *
5276 * Only when a remote device provides an identity address
5277 * make sure the long term key is stored. If the remote
5278 * identity is known, the long term keys are internally
5279 * mapped to the identity address. So allow static random
5280 * and public addresses here.
5281 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005282 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5283 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5284 ev.store_hint = 0x00;
5285 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005286 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005287
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005288 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005289 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005290 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005291 ev.key.enc_size = key->enc_size;
5292 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005293 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005294
Johan Hedberg2ceba532014-06-16 19:25:16 +03005295 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005296 ev.key.master = 1;
5297
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005298 memcpy(ev.key.val, key->val, sizeof(key->val));
5299
Marcel Holtmann083368f2013-10-15 14:26:29 -07005300 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005301}
5302
Johan Hedberg95fbac82014-02-19 15:18:31 +02005303void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5304{
5305 struct mgmt_ev_new_irk ev;
5306
5307 memset(&ev, 0, sizeof(ev));
5308
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005309 /* For identity resolving keys from devices that are already
5310 * using a public address or static random address, do not
5311 * ask for storing this key. The identity resolving key really
5312 * is only mandatory for devices using resovlable random
5313 * addresses.
5314 *
5315 * Storing all identity resolving keys has the downside that
5316 * they will be also loaded on next boot of they system. More
5317 * identity resolving keys, means more time during scanning is
5318 * needed to actually resolve these addresses.
5319 */
5320 if (bacmp(&irk->rpa, BDADDR_ANY))
5321 ev.store_hint = 0x01;
5322 else
5323 ev.store_hint = 0x00;
5324
Johan Hedberg95fbac82014-02-19 15:18:31 +02005325 bacpy(&ev.rpa, &irk->rpa);
5326 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5327 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5328 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5329
5330 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5331}
5332
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005333void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5334 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005335{
5336 struct mgmt_ev_new_csrk ev;
5337
5338 memset(&ev, 0, sizeof(ev));
5339
5340 /* Devices using resolvable or non-resolvable random addresses
5341 * without providing an indentity resolving key don't require
5342 * to store signature resolving keys. Their addresses will change
5343 * the next time around.
5344 *
5345 * Only when a remote device provides an identity address
5346 * make sure the signature resolving key is stored. So allow
5347 * static random and public addresses here.
5348 */
5349 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5350 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5351 ev.store_hint = 0x00;
5352 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005353 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005354
5355 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5356 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5357 ev.key.master = csrk->master;
5358 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5359
5360 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5361}
5362
Marcel Holtmann94933992013-10-15 10:26:39 -07005363static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5364 u8 data_len)
5365{
5366 eir[eir_len++] = sizeof(type) + data_len;
5367 eir[eir_len++] = type;
5368 memcpy(&eir[eir_len], data, data_len);
5369 eir_len += data_len;
5370
5371 return eir_len;
5372}
5373
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005374void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5375 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5376 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005377{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005378 char buf[512];
5379 struct mgmt_ev_device_connected *ev = (void *) buf;
5380 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005381
Johan Hedbergb644ba32012-01-17 21:48:47 +02005382 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005383 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005384
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005385 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005386
Johan Hedbergb644ba32012-01-17 21:48:47 +02005387 if (name_len > 0)
5388 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005389 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005390
5391 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005392 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005393 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005394
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005395 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005396
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005397 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5398 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005399}
5400
Johan Hedberg8962ee72011-01-20 12:40:27 +02005401static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5402{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005403 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005404 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005405 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005406
Johan Hedberg88c3df12012-02-09 14:27:38 +02005407 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5408 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005409
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005410 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005411 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005412
5413 *sk = cmd->sk;
5414 sock_hold(*sk);
5415
Johan Hedberga664b5b2011-02-19 12:06:02 -03005416 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005417}
5418
Johan Hedberg124f6e32012-02-09 13:50:12 +02005419static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005420{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005421 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005422 struct mgmt_cp_unpair_device *cp = cmd->param;
5423 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005424
5425 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005426 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5427 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005428
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005429 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5430
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005431 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005432
5433 mgmt_pending_remove(cmd);
5434}
5435
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005436void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005437 u8 link_type, u8 addr_type, u8 reason,
5438 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005439{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005440 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005441 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005442 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005443
Johan Hedberg8b064a32014-02-24 14:52:22 +02005444 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5445 if (power_off) {
5446 struct mgmt_mode *cp = power_off->param;
5447
5448 /* The connection is still in hci_conn_hash so test for 1
5449 * instead of 0 to know if this is the last one.
5450 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005451 if (!cp->val && hci_conn_count(hdev) == 1) {
5452 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005453 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005454 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005455 }
5456
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005457 if (!mgmt_connected)
5458 return;
5459
Andre Guedes57eb7762013-10-30 19:01:41 -03005460 if (link_type != ACL_LINK && link_type != LE_LINK)
5461 return;
5462
Johan Hedberg744cf192011-11-08 20:40:14 +02005463 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005464
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005465 bacpy(&ev.addr.bdaddr, bdaddr);
5466 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5467 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005468
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005469 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005470
5471 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005472 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005473
Johan Hedberg124f6e32012-02-09 13:50:12 +02005474 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005475 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005476}
5477
Marcel Holtmann78929242013-10-06 23:55:47 -07005478void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5479 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005480{
Andre Guedes3655bba2013-10-30 19:01:40 -03005481 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5482 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005483 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005484 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005485
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005486 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5487 hdev);
5488
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005489 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005490 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005491 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005492
Andre Guedes3655bba2013-10-30 19:01:40 -03005493 cp = cmd->param;
5494
5495 if (bacmp(bdaddr, &cp->addr.bdaddr))
5496 return;
5497
5498 if (cp->addr.type != bdaddr_type)
5499 return;
5500
Johan Hedberg88c3df12012-02-09 14:27:38 +02005501 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005502 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005503
Marcel Holtmann78929242013-10-06 23:55:47 -07005504 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5505 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005506
Johan Hedberga664b5b2011-02-19 12:06:02 -03005507 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005508}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005509
Marcel Holtmann445608d2013-10-06 23:55:48 -07005510void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5511 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005512{
5513 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005514 struct pending_cmd *power_off;
5515
5516 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5517 if (power_off) {
5518 struct mgmt_mode *cp = power_off->param;
5519
5520 /* The connection is still in hci_conn_hash so test for 1
5521 * instead of 0 to know if this is the last one.
5522 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005523 if (!cp->val && hci_conn_count(hdev) == 1) {
5524 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005525 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005526 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005527 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005528
Johan Hedberg4c659c32011-11-07 23:13:39 +02005529 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005530 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005531 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005532
Marcel Holtmann445608d2013-10-06 23:55:48 -07005533 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005534}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005535
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005536void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005537{
5538 struct mgmt_ev_pin_code_request ev;
5539
Johan Hedbergd8457692012-02-17 14:24:57 +02005540 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005541 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005542 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005543
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005544 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005545}
5546
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005547void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5548 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005549{
5550 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005551 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005552
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005553 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005554 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005555 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005556
Johan Hedbergd8457692012-02-17 14:24:57 +02005557 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005558 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005559
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005560 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5561 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005562
Johan Hedberga664b5b2011-02-19 12:06:02 -03005563 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005564}
5565
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005566void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5567 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005568{
5569 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005570 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005571
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005572 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005573 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005574 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005575
Johan Hedbergd8457692012-02-17 14:24:57 +02005576 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005577 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005578
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005579 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5580 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005581
Johan Hedberga664b5b2011-02-19 12:06:02 -03005582 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005583}
Johan Hedberga5c29682011-02-19 12:05:57 -03005584
Johan Hedberg744cf192011-11-08 20:40:14 +02005585int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005586 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005587 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005588{
5589 struct mgmt_ev_user_confirm_request ev;
5590
Johan Hedberg744cf192011-11-08 20:40:14 +02005591 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005592
Johan Hedberg272d90d2012-02-09 15:26:12 +02005593 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005594 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005595 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005596 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005597
Johan Hedberg744cf192011-11-08 20:40:14 +02005598 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005599 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005600}
5601
Johan Hedberg272d90d2012-02-09 15:26:12 +02005602int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005603 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005604{
5605 struct mgmt_ev_user_passkey_request ev;
5606
5607 BT_DBG("%s", hdev->name);
5608
Johan Hedberg272d90d2012-02-09 15:26:12 +02005609 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005610 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005611
5612 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005613 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005614}
5615
Brian Gix0df4c182011-11-16 13:53:13 -08005616static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005617 u8 link_type, u8 addr_type, u8 status,
5618 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005619{
5620 struct pending_cmd *cmd;
5621 struct mgmt_rp_user_confirm_reply rp;
5622 int err;
5623
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005624 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005625 if (!cmd)
5626 return -ENOENT;
5627
Johan Hedberg272d90d2012-02-09 15:26:12 +02005628 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005629 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005630 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005631 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005632
Johan Hedberga664b5b2011-02-19 12:06:02 -03005633 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005634
5635 return err;
5636}
5637
Johan Hedberg744cf192011-11-08 20:40:14 +02005638int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005639 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005640{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005641 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005642 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005643}
5644
Johan Hedberg272d90d2012-02-09 15:26:12 +02005645int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005646 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005647{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005648 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005649 status,
5650 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005651}
Johan Hedberg2a611692011-02-19 12:06:00 -03005652
Brian Gix604086b2011-11-23 08:28:33 -08005653int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005654 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005655{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005656 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005657 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005658}
5659
Johan Hedberg272d90d2012-02-09 15:26:12 +02005660int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005661 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005662{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005663 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005664 status,
5665 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005666}
5667
Johan Hedberg92a25252012-09-06 18:39:26 +03005668int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5669 u8 link_type, u8 addr_type, u32 passkey,
5670 u8 entered)
5671{
5672 struct mgmt_ev_passkey_notify ev;
5673
5674 BT_DBG("%s", hdev->name);
5675
5676 bacpy(&ev.addr.bdaddr, bdaddr);
5677 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5678 ev.passkey = __cpu_to_le32(passkey);
5679 ev.entered = entered;
5680
5681 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5682}
5683
Marcel Holtmanne5460992013-10-15 14:26:23 -07005684void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5685 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005686{
5687 struct mgmt_ev_auth_failed ev;
5688
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005689 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005690 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005691 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005692
Marcel Holtmanne5460992013-10-15 14:26:23 -07005693 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005694}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005695
Marcel Holtmann464996a2013-10-15 14:26:24 -07005696void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005697{
5698 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005699 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005700
5701 if (status) {
5702 u8 mgmt_err = mgmt_status(status);
5703 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005704 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005705 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005706 }
5707
Marcel Holtmann464996a2013-10-15 14:26:24 -07005708 if (test_bit(HCI_AUTH, &hdev->flags))
5709 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5710 &hdev->dev_flags);
5711 else
5712 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5713 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005714
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005715 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005716 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005717
Johan Hedberg47990ea2012-02-22 11:58:37 +02005718 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005719 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005720
5721 if (match.sk)
5722 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005723}
5724
Johan Hedberg890ea892013-03-15 17:06:52 -05005725static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005726{
Johan Hedberg890ea892013-03-15 17:06:52 -05005727 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005728 struct hci_cp_write_eir cp;
5729
Johan Hedberg976eb202012-10-24 21:12:01 +03005730 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005731 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005732
Johan Hedbergc80da272012-02-22 15:38:48 +02005733 memset(hdev->eir, 0, sizeof(hdev->eir));
5734
Johan Hedbergcacaf522012-02-21 00:52:42 +02005735 memset(&cp, 0, sizeof(cp));
5736
Johan Hedberg890ea892013-03-15 17:06:52 -05005737 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005738}
5739
Marcel Holtmann3e248562013-10-15 14:26:25 -07005740void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005741{
5742 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005743 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005744 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005745
5746 if (status) {
5747 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005748
5749 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005750 &hdev->dev_flags)) {
5751 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005752 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005753 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005754
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005755 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5756 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005757 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005758 }
5759
5760 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005761 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005762 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005763 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5764 if (!changed)
5765 changed = test_and_clear_bit(HCI_HS_ENABLED,
5766 &hdev->dev_flags);
5767 else
5768 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005769 }
5770
5771 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5772
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005773 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005774 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005775
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005776 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005777 sock_put(match.sk);
5778
Johan Hedberg890ea892013-03-15 17:06:52 -05005779 hci_req_init(&req, hdev);
5780
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005781 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005782 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005783 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005784 clear_eir(&req);
5785
5786 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005787}
5788
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005789void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5790{
5791 struct cmd_lookup match = { NULL, hdev };
5792 bool changed = false;
5793
5794 if (status) {
5795 u8 mgmt_err = mgmt_status(status);
5796
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005797 if (enable) {
5798 if (test_and_clear_bit(HCI_SC_ENABLED,
5799 &hdev->dev_flags))
5800 new_settings(hdev, NULL);
5801 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5802 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005803
5804 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5805 cmd_status_rsp, &mgmt_err);
5806 return;
5807 }
5808
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005809 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005810 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005811 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005812 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005813 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5814 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005815
5816 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5817 settings_rsp, &match);
5818
5819 if (changed)
5820 new_settings(hdev, match.sk);
5821
5822 if (match.sk)
5823 sock_put(match.sk);
5824}
5825
Johan Hedberg92da6092013-03-15 17:06:55 -05005826static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005827{
5828 struct cmd_lookup *match = data;
5829
Johan Hedberg90e70452012-02-23 23:09:40 +02005830 if (match->sk == NULL) {
5831 match->sk = cmd->sk;
5832 sock_hold(match->sk);
5833 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005834}
5835
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005836void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5837 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005838{
Johan Hedberg90e70452012-02-23 23:09:40 +02005839 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005840
Johan Hedberg92da6092013-03-15 17:06:55 -05005841 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5842 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5843 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005844
5845 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005846 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5847 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005848
5849 if (match.sk)
5850 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005851}
5852
Marcel Holtmann7667da32013-10-15 14:26:27 -07005853void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005854{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005855 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005856 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005857
Johan Hedberg13928972013-03-15 17:07:00 -05005858 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005859 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005860
5861 memset(&ev, 0, sizeof(ev));
5862 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005863 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005864
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005865 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005866 if (!cmd) {
5867 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005868
Johan Hedberg13928972013-03-15 17:07:00 -05005869 /* If this is a HCI command related to powering on the
5870 * HCI dev don't send any mgmt signals.
5871 */
5872 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005873 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005874 }
5875
Marcel Holtmann7667da32013-10-15 14:26:27 -07005876 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5877 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005878}
Szymon Jancc35938b2011-03-22 13:12:21 +01005879
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005880void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5881 u8 *randomizer192, u8 *hash256,
5882 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005883{
5884 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005885
Johan Hedberg744cf192011-11-08 20:40:14 +02005886 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005887
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005888 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005889 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005890 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005891
5892 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005893 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5894 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005895 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005896 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5897 hash256 && randomizer256) {
5898 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005899
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005900 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5901 memcpy(rp.randomizer192, randomizer192,
5902 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005903
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005904 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5905 memcpy(rp.randomizer256, randomizer256,
5906 sizeof(rp.randomizer256));
5907
5908 cmd_complete(cmd->sk, hdev->id,
5909 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5910 &rp, sizeof(rp));
5911 } else {
5912 struct mgmt_rp_read_local_oob_data rp;
5913
5914 memcpy(rp.hash, hash192, sizeof(rp.hash));
5915 memcpy(rp.randomizer, randomizer192,
5916 sizeof(rp.randomizer));
5917
5918 cmd_complete(cmd->sk, hdev->id,
5919 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5920 &rp, sizeof(rp));
5921 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005922 }
5923
5924 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005925}
Johan Hedberge17acd42011-03-30 23:57:16 +03005926
Marcel Holtmann901801b2013-10-06 23:55:51 -07005927void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02005928 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
5929 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005930 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005931{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005932 char buf[512];
5933 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005934 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005935 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005936
Andre Guedes12602d02013-04-30 15:29:40 -03005937 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005938 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005939
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005940 /* Make sure that the buffer is big enough. The 5 extra bytes
5941 * are for the potential CoD field.
5942 */
5943 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005944 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005945
Johan Hedberg1dc06092012-01-15 21:01:23 +02005946 memset(buf, 0, sizeof(buf));
5947
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005948 irk = hci_get_irk(hdev, bdaddr, addr_type);
5949 if (irk) {
5950 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5951 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5952 } else {
5953 bacpy(&ev->addr.bdaddr, bdaddr);
5954 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5955 }
5956
Johan Hedberge319d2e2012-01-15 19:51:59 +02005957 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005958 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005959 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005960 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005961 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005962
Johan Hedberg1dc06092012-01-15 21:01:23 +02005963 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005964 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005965
Johan Hedberg1dc06092012-01-15 21:01:23 +02005966 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5967 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005968 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005969
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005970 if (scan_rsp_len > 0)
5971 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
5972
5973 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
5974 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005975
Marcel Holtmann901801b2013-10-06 23:55:51 -07005976 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005977}
Johan Hedberga88a9652011-03-30 13:18:12 +03005978
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005979void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5980 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005981{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005982 struct mgmt_ev_device_found *ev;
5983 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5984 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005985
Johan Hedbergb644ba32012-01-17 21:48:47 +02005986 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005987
Johan Hedbergb644ba32012-01-17 21:48:47 +02005988 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005989
Johan Hedbergb644ba32012-01-17 21:48:47 +02005990 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005991 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005992 ev->rssi = rssi;
5993
5994 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005995 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005996
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005997 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005998
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005999 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006000}
Johan Hedberg314b2382011-04-27 10:29:57 -04006001
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006002void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006003{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006004 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006005 struct pending_cmd *cmd;
6006
Andre Guedes343fb142011-11-22 17:14:19 -03006007 BT_DBG("%s discovering %u", hdev->name, discovering);
6008
Johan Hedberg164a6e72011-11-01 17:06:44 +02006009 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006010 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006011 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006012 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006013
6014 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006015 u8 type = hdev->discovery.type;
6016
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006017 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6018 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006019 mgmt_pending_remove(cmd);
6020 }
6021
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006022 memset(&ev, 0, sizeof(ev));
6023 ev.type = hdev->discovery.type;
6024 ev.discovering = discovering;
6025
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006026 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006027}
Antti Julku5e762442011-08-25 16:48:02 +03006028
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006029int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006030{
6031 struct pending_cmd *cmd;
6032 struct mgmt_ev_device_blocked ev;
6033
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006034 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006035
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006036 bacpy(&ev.addr.bdaddr, bdaddr);
6037 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006038
Johan Hedberg744cf192011-11-08 20:40:14 +02006039 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006040 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006041}
6042
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006043int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006044{
6045 struct pending_cmd *cmd;
6046 struct mgmt_ev_device_unblocked ev;
6047
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006048 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006049
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006050 bacpy(&ev.addr.bdaddr, bdaddr);
6051 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006052
Johan Hedberg744cf192011-11-08 20:40:14 +02006053 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006054 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006055}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006056
6057static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6058{
6059 BT_DBG("%s status %u", hdev->name, status);
6060
6061 /* Clear the advertising mgmt setting if we failed to re-enable it */
6062 if (status) {
6063 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006064 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006065 }
6066}
6067
6068void mgmt_reenable_advertising(struct hci_dev *hdev)
6069{
6070 struct hci_request req;
6071
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006072 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006073 return;
6074
6075 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6076 return;
6077
6078 hci_req_init(&req, hdev);
6079 enable_advertising(&req);
6080
6081 /* If this fails we have no option but to let user space know
6082 * that we've disabled advertising.
6083 */
6084 if (hci_req_run(&req, adv_enable_complete) < 0) {
6085 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006086 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006087 }
6088}