blob: 4522da18d8e52a4ac3d758c661a8f8ccde7df517 [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>
32#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070033
34#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020035
Johan Hedberg2da9c552012-02-17 14:39:28 +020036#define MGMT_VERSION 1
Marcel Holtmann404566442014-01-28 15:39:01 -080037#define MGMT_REVISION 5
Johan Hedberg02d98122010-12-13 21:07:04 +020038
Johan Hedberge70bb2e2012-02-13 16:59:33 +020039static const u16 mgmt_commands[] = {
40 MGMT_OP_READ_INDEX_LIST,
41 MGMT_OP_READ_INFO,
42 MGMT_OP_SET_POWERED,
43 MGMT_OP_SET_DISCOVERABLE,
44 MGMT_OP_SET_CONNECTABLE,
45 MGMT_OP_SET_FAST_CONNECTABLE,
46 MGMT_OP_SET_PAIRABLE,
47 MGMT_OP_SET_LINK_SECURITY,
48 MGMT_OP_SET_SSP,
49 MGMT_OP_SET_HS,
50 MGMT_OP_SET_LE,
51 MGMT_OP_SET_DEV_CLASS,
52 MGMT_OP_SET_LOCAL_NAME,
53 MGMT_OP_ADD_UUID,
54 MGMT_OP_REMOVE_UUID,
55 MGMT_OP_LOAD_LINK_KEYS,
56 MGMT_OP_LOAD_LONG_TERM_KEYS,
57 MGMT_OP_DISCONNECT,
58 MGMT_OP_GET_CONNECTIONS,
59 MGMT_OP_PIN_CODE_REPLY,
60 MGMT_OP_PIN_CODE_NEG_REPLY,
61 MGMT_OP_SET_IO_CAPABILITY,
62 MGMT_OP_PAIR_DEVICE,
63 MGMT_OP_CANCEL_PAIR_DEVICE,
64 MGMT_OP_UNPAIR_DEVICE,
65 MGMT_OP_USER_CONFIRM_REPLY,
66 MGMT_OP_USER_CONFIRM_NEG_REPLY,
67 MGMT_OP_USER_PASSKEY_REPLY,
68 MGMT_OP_USER_PASSKEY_NEG_REPLY,
69 MGMT_OP_READ_LOCAL_OOB_DATA,
70 MGMT_OP_ADD_REMOTE_OOB_DATA,
71 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
72 MGMT_OP_START_DISCOVERY,
73 MGMT_OP_STOP_DISCOVERY,
74 MGMT_OP_CONFIRM_NAME,
75 MGMT_OP_BLOCK_DEVICE,
76 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070077 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030078 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030079 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070080 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070081 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080082 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080083 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg41edf162014-02-18 10:19:35 +020084 MGMT_OP_LOAD_IRKS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020085};
86
87static const u16 mgmt_events[] = {
88 MGMT_EV_CONTROLLER_ERROR,
89 MGMT_EV_INDEX_ADDED,
90 MGMT_EV_INDEX_REMOVED,
91 MGMT_EV_NEW_SETTINGS,
92 MGMT_EV_CLASS_OF_DEV_CHANGED,
93 MGMT_EV_LOCAL_NAME_CHANGED,
94 MGMT_EV_NEW_LINK_KEY,
95 MGMT_EV_NEW_LONG_TERM_KEY,
96 MGMT_EV_DEVICE_CONNECTED,
97 MGMT_EV_DEVICE_DISCONNECTED,
98 MGMT_EV_CONNECT_FAILED,
99 MGMT_EV_PIN_CODE_REQUEST,
100 MGMT_EV_USER_CONFIRM_REQUEST,
101 MGMT_EV_USER_PASSKEY_REQUEST,
102 MGMT_EV_AUTH_FAILED,
103 MGMT_EV_DEVICE_FOUND,
104 MGMT_EV_DISCOVERING,
105 MGMT_EV_DEVICE_BLOCKED,
106 MGMT_EV_DEVICE_UNBLOCKED,
107 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300108 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800109 MGMT_EV_NEW_IRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200110};
111
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800112#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200113
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200114#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
115 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
116
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200117struct pending_cmd {
118 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200119 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200120 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100121 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200122 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300123 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200124};
125
Johan Hedbergca69b792011-11-11 18:10:00 +0200126/* HCI to MGMT error code conversion table */
127static u8 mgmt_status_table[] = {
128 MGMT_STATUS_SUCCESS,
129 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
130 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
131 MGMT_STATUS_FAILED, /* Hardware Failure */
132 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
133 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200134 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200135 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
136 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
137 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
138 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
139 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
140 MGMT_STATUS_BUSY, /* Command Disallowed */
141 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
142 MGMT_STATUS_REJECTED, /* Rejected Security */
143 MGMT_STATUS_REJECTED, /* Rejected Personal */
144 MGMT_STATUS_TIMEOUT, /* Host Timeout */
145 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
146 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
147 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
148 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
149 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
150 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
151 MGMT_STATUS_BUSY, /* Repeated Attempts */
152 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
153 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
154 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
155 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
156 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
157 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
158 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
159 MGMT_STATUS_FAILED, /* Unspecified Error */
160 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
161 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
162 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
163 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
164 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
165 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
166 MGMT_STATUS_FAILED, /* Unit Link Key Used */
167 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
168 MGMT_STATUS_TIMEOUT, /* Instant Passed */
169 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
170 MGMT_STATUS_FAILED, /* Transaction Collision */
171 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
172 MGMT_STATUS_REJECTED, /* QoS Rejected */
173 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
174 MGMT_STATUS_REJECTED, /* Insufficient Security */
175 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
176 MGMT_STATUS_BUSY, /* Role Switch Pending */
177 MGMT_STATUS_FAILED, /* Slot Violation */
178 MGMT_STATUS_FAILED, /* Role Switch Failed */
179 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
180 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
181 MGMT_STATUS_BUSY, /* Host Busy Pairing */
182 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
183 MGMT_STATUS_BUSY, /* Controller Busy */
184 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
185 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
186 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
187 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
188 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
189};
190
191static u8 mgmt_status(u8 hci_status)
192{
193 if (hci_status < ARRAY_SIZE(mgmt_status_table))
194 return mgmt_status_table[hci_status];
195
196 return MGMT_STATUS_FAILED;
197}
198
Szymon Janc4e51eae2011-02-25 19:05:48 +0100199static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200200{
201 struct sk_buff *skb;
202 struct mgmt_hdr *hdr;
203 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300204 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200205
Szymon Janc34eb5252011-02-28 14:10:08 +0100206 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200207
Andre Guedes790eff42012-06-07 19:05:46 -0300208 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200209 if (!skb)
210 return -ENOMEM;
211
212 hdr = (void *) skb_put(skb, sizeof(*hdr));
213
Syam Sidhardhan612dfce2012-10-29 22:37:36 +0530214 hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100215 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200216 hdr->len = cpu_to_le16(sizeof(*ev));
217
218 ev = (void *) skb_put(skb, sizeof(*ev));
219 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200220 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200221
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300222 err = sock_queue_rcv_skb(sk, skb);
223 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200224 kfree_skb(skb);
225
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300226 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200227}
228
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200229static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300230 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200231{
232 struct sk_buff *skb;
233 struct mgmt_hdr *hdr;
234 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300235 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200236
237 BT_DBG("sock %p", sk);
238
Andre Guedes790eff42012-06-07 19:05:46 -0300239 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200240 if (!skb)
241 return -ENOMEM;
242
243 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200244
Syam Sidhardhan612dfce2012-10-29 22:37:36 +0530245 hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100246 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200247 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200248
Johan Hedberga38528f2011-01-22 06:46:43 +0200249 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200250 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200251 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100252
253 if (rp)
254 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200255
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300256 err = sock_queue_rcv_skb(sk, skb);
257 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200258 kfree_skb(skb);
259
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100260 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200261}
262
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300263static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
264 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200265{
266 struct mgmt_rp_read_version rp;
267
268 BT_DBG("sock %p", sk);
269
270 rp.version = MGMT_VERSION;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200271 rp.revision = __constant_cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200272
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200273 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300274 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200275}
276
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300277static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
278 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200279{
280 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200281 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
282 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200283 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200284 size_t rp_size;
285 int i, err;
286
287 BT_DBG("sock %p", sk);
288
289 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
290
291 rp = kmalloc(rp_size, GFP_KERNEL);
292 if (!rp)
293 return -ENOMEM;
294
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200295 rp->num_commands = __constant_cpu_to_le16(num_commands);
296 rp->num_events = __constant_cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200297
298 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
299 put_unaligned_le16(mgmt_commands[i], opcode);
300
301 for (i = 0; i < num_events; i++, opcode++)
302 put_unaligned_le16(mgmt_events[i], opcode);
303
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200304 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300305 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200306 kfree(rp);
307
308 return err;
309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200313{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200314 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200315 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200316 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200317 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300318 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200319
320 BT_DBG("sock %p", sk);
321
322 read_lock(&hci_dev_list_lock);
323
324 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300325 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700326 if (d->dev_type == HCI_BREDR)
327 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200328 }
329
Johan Hedberga38528f2011-01-22 06:46:43 +0200330 rp_len = sizeof(*rp) + (2 * count);
331 rp = kmalloc(rp_len, GFP_ATOMIC);
332 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100333 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200334 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100335 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200336
Johan Hedberg476e44c2012-10-19 20:10:46 +0300337 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200338 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200339 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200340 continue;
341
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700342 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
343 continue;
344
Marcel Holtmann1514b892013-10-06 08:25:01 -0700345 if (d->dev_type == HCI_BREDR) {
346 rp->index[count++] = cpu_to_le16(d->id);
347 BT_DBG("Added hci%u", d->id);
348 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200349 }
350
Johan Hedberg476e44c2012-10-19 20:10:46 +0300351 rp->num_controllers = cpu_to_le16(count);
352 rp_len = sizeof(*rp) + (2 * count);
353
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200354 read_unlock(&hci_dev_list_lock);
355
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200356 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300357 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200358
Johan Hedberga38528f2011-01-22 06:46:43 +0200359 kfree(rp);
360
361 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362}
363
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200364static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200365{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200366 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200367
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200368 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200369 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800370 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200371
Andre Guedesed3fa312012-07-24 15:03:46 -0300372 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300373 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500374 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
375 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300376 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200377 settings |= MGMT_SETTING_BREDR;
378 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700379
380 if (lmp_ssp_capable(hdev)) {
381 settings |= MGMT_SETTING_SSP;
382 settings |= MGMT_SETTING_HS;
383 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800384
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800385 if (lmp_sc_capable(hdev) ||
386 test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800387 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700388 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100389
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300390 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200391 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300392 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200393 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300394 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200395
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200396 return settings;
397}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200398
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200399static u32 get_current_settings(struct hci_dev *hdev)
400{
401 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200402
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200403 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100404 settings |= MGMT_SETTING_POWERED;
405
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200406 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200407 settings |= MGMT_SETTING_CONNECTABLE;
408
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500409 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
410 settings |= MGMT_SETTING_FAST_CONNECTABLE;
411
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200412 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200413 settings |= MGMT_SETTING_DISCOVERABLE;
414
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200415 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200416 settings |= MGMT_SETTING_PAIRABLE;
417
Johan Hedberg56f87902013-10-02 13:43:13 +0300418 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200419 settings |= MGMT_SETTING_BREDR;
420
Johan Hedberg06199cf2012-02-22 16:37:11 +0200421 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200422 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200423
Johan Hedberg47990ea2012-02-22 11:58:37 +0200424 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200425 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200426
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200427 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200428 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200429
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200430 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
431 settings |= MGMT_SETTING_HS;
432
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200433 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300434 settings |= MGMT_SETTING_ADVERTISING;
435
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800436 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
437 settings |= MGMT_SETTING_SECURE_CONN;
438
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800439 if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags))
440 settings |= MGMT_SETTING_DEBUG_KEYS;
441
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200442 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
443 settings |= MGMT_SETTING_PRIVACY;
444
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200445 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200446}
447
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300448#define PNP_INFO_SVCLASS_ID 0x1200
449
Johan Hedberg213202e2013-01-27 00:31:33 +0200450static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
451{
452 u8 *ptr = data, *uuids_start = NULL;
453 struct bt_uuid *uuid;
454
455 if (len < 4)
456 return ptr;
457
458 list_for_each_entry(uuid, &hdev->uuids, list) {
459 u16 uuid16;
460
461 if (uuid->size != 16)
462 continue;
463
464 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
465 if (uuid16 < 0x1100)
466 continue;
467
468 if (uuid16 == PNP_INFO_SVCLASS_ID)
469 continue;
470
471 if (!uuids_start) {
472 uuids_start = ptr;
473 uuids_start[0] = 1;
474 uuids_start[1] = EIR_UUID16_ALL;
475 ptr += 2;
476 }
477
478 /* Stop if not enough space to put next UUID */
479 if ((ptr - data) + sizeof(u16) > len) {
480 uuids_start[1] = EIR_UUID16_SOME;
481 break;
482 }
483
484 *ptr++ = (uuid16 & 0x00ff);
485 *ptr++ = (uuid16 & 0xff00) >> 8;
486 uuids_start[0] += sizeof(uuid16);
487 }
488
489 return ptr;
490}
491
Johan Hedbergcdf19632013-01-27 00:31:34 +0200492static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
493{
494 u8 *ptr = data, *uuids_start = NULL;
495 struct bt_uuid *uuid;
496
497 if (len < 6)
498 return ptr;
499
500 list_for_each_entry(uuid, &hdev->uuids, list) {
501 if (uuid->size != 32)
502 continue;
503
504 if (!uuids_start) {
505 uuids_start = ptr;
506 uuids_start[0] = 1;
507 uuids_start[1] = EIR_UUID32_ALL;
508 ptr += 2;
509 }
510
511 /* Stop if not enough space to put next UUID */
512 if ((ptr - data) + sizeof(u32) > len) {
513 uuids_start[1] = EIR_UUID32_SOME;
514 break;
515 }
516
517 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
518 ptr += sizeof(u32);
519 uuids_start[0] += sizeof(u32);
520 }
521
522 return ptr;
523}
524
Johan Hedbergc00d5752013-01-27 00:31:35 +0200525static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
526{
527 u8 *ptr = data, *uuids_start = NULL;
528 struct bt_uuid *uuid;
529
530 if (len < 18)
531 return ptr;
532
533 list_for_each_entry(uuid, &hdev->uuids, list) {
534 if (uuid->size != 128)
535 continue;
536
537 if (!uuids_start) {
538 uuids_start = ptr;
539 uuids_start[0] = 1;
540 uuids_start[1] = EIR_UUID128_ALL;
541 ptr += 2;
542 }
543
544 /* Stop if not enough space to put next UUID */
545 if ((ptr - data) + 16 > len) {
546 uuids_start[1] = EIR_UUID128_SOME;
547 break;
548 }
549
550 memcpy(ptr, uuid->uuid, 16);
551 ptr += 16;
552 uuids_start[0] += 16;
553 }
554
555 return ptr;
556}
557
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300558static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
559{
560 struct pending_cmd *cmd;
561
562 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
563 if (cmd->opcode == opcode)
564 return cmd;
565 }
566
567 return NULL;
568}
569
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700570static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
571{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700572 u8 ad_len = 0;
573 size_t name_len;
574
575 name_len = strlen(hdev->dev_name);
576 if (name_len > 0) {
577 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
578
579 if (name_len > max_len) {
580 name_len = max_len;
581 ptr[1] = EIR_NAME_SHORT;
582 } else
583 ptr[1] = EIR_NAME_COMPLETE;
584
585 ptr[0] = name_len + 1;
586
587 memcpy(ptr + 2, hdev->dev_name, name_len);
588
589 ad_len += (name_len + 2);
590 ptr += (name_len + 2);
591 }
592
593 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700594}
595
596static void update_scan_rsp_data(struct hci_request *req)
597{
598 struct hci_dev *hdev = req->hdev;
599 struct hci_cp_le_set_scan_rsp_data cp;
600 u8 len;
601
Johan Hedberg7751ef12013-10-19 23:38:15 +0300602 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700603 return;
604
605 memset(&cp, 0, sizeof(cp));
606
607 len = create_scan_rsp_data(hdev, cp.data);
608
Johan Hedbergeb438b52013-10-16 15:31:07 +0300609 if (hdev->scan_rsp_data_len == len &&
610 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700611 return;
612
Johan Hedbergeb438b52013-10-16 15:31:07 +0300613 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
614 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700615
616 cp.length = len;
617
618 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
619}
620
Johan Hedberg9a43e252013-10-20 19:00:07 +0300621static u8 get_adv_discov_flags(struct hci_dev *hdev)
622{
623 struct pending_cmd *cmd;
624
625 /* If there's a pending mgmt command the flags will not yet have
626 * their final values, so check for this first.
627 */
628 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
629 if (cmd) {
630 struct mgmt_mode *cp = cmd->param;
631 if (cp->val == 0x01)
632 return LE_AD_GENERAL;
633 else if (cp->val == 0x02)
634 return LE_AD_LIMITED;
635 } else {
636 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
637 return LE_AD_LIMITED;
638 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
639 return LE_AD_GENERAL;
640 }
641
642 return 0;
643}
644
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700645static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700646{
647 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700648
Johan Hedberg9a43e252013-10-20 19:00:07 +0300649 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700650
Johan Hedberge8340042014-01-30 11:16:50 -0800651 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700652 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700653
654 if (flags) {
655 BT_DBG("adv flags 0x%02x", flags);
656
657 ptr[0] = 2;
658 ptr[1] = EIR_FLAGS;
659 ptr[2] = flags;
660
661 ad_len += 3;
662 ptr += 3;
663 }
664
665 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
666 ptr[0] = 2;
667 ptr[1] = EIR_TX_POWER;
668 ptr[2] = (u8) hdev->adv_tx_power;
669
670 ad_len += 3;
671 ptr += 3;
672 }
673
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700674 return ad_len;
675}
676
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700677static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678{
679 struct hci_dev *hdev = req->hdev;
680 struct hci_cp_le_set_adv_data cp;
681 u8 len;
682
Johan Hedberg10994ce2013-10-19 23:38:16 +0300683 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700684 return;
685
686 memset(&cp, 0, sizeof(cp));
687
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700688 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700689
690 if (hdev->adv_data_len == len &&
691 memcmp(cp.data, hdev->adv_data, len) == 0)
692 return;
693
694 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
695 hdev->adv_data_len = len;
696
697 cp.length = len;
698
699 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
700}
701
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300702static void create_eir(struct hci_dev *hdev, u8 *data)
703{
704 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300705 size_t name_len;
706
707 name_len = strlen(hdev->dev_name);
708
709 if (name_len > 0) {
710 /* EIR Data type */
711 if (name_len > 48) {
712 name_len = 48;
713 ptr[1] = EIR_NAME_SHORT;
714 } else
715 ptr[1] = EIR_NAME_COMPLETE;
716
717 /* EIR Data length */
718 ptr[0] = name_len + 1;
719
720 memcpy(ptr + 2, hdev->dev_name, name_len);
721
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300722 ptr += (name_len + 2);
723 }
724
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100725 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700726 ptr[0] = 2;
727 ptr[1] = EIR_TX_POWER;
728 ptr[2] = (u8) hdev->inq_tx_power;
729
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700730 ptr += 3;
731 }
732
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700733 if (hdev->devid_source > 0) {
734 ptr[0] = 9;
735 ptr[1] = EIR_DEVICE_ID;
736
737 put_unaligned_le16(hdev->devid_source, ptr + 2);
738 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
739 put_unaligned_le16(hdev->devid_product, ptr + 6);
740 put_unaligned_le16(hdev->devid_version, ptr + 8);
741
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700742 ptr += 10;
743 }
744
Johan Hedberg213202e2013-01-27 00:31:33 +0200745 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200746 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200747 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300748}
749
Johan Hedberg890ea892013-03-15 17:06:52 -0500750static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300751{
Johan Hedberg890ea892013-03-15 17:06:52 -0500752 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300753 struct hci_cp_write_eir cp;
754
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200755 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500756 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200757
Johan Hedberg976eb202012-10-24 21:12:01 +0300758 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500759 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300760
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200761 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500762 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300763
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200764 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500765 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300766
767 memset(&cp, 0, sizeof(cp));
768
769 create_eir(hdev, cp.data);
770
771 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500772 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300773
774 memcpy(hdev->eir, cp.data, sizeof(cp.data));
775
Johan Hedberg890ea892013-03-15 17:06:52 -0500776 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300777}
778
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200779static u8 get_service_classes(struct hci_dev *hdev)
780{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300781 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200782 u8 val = 0;
783
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300784 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200785 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200786
787 return val;
788}
789
Johan Hedberg890ea892013-03-15 17:06:52 -0500790static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200791{
Johan Hedberg890ea892013-03-15 17:06:52 -0500792 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200793 u8 cod[3];
794
795 BT_DBG("%s", hdev->name);
796
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200797 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500798 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200799
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300800 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
801 return;
802
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200803 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500804 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200805
806 cod[0] = hdev->minor_class;
807 cod[1] = hdev->major_class;
808 cod[2] = get_service_classes(hdev);
809
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700810 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
811 cod[1] |= 0x20;
812
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200813 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500814 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200815
Johan Hedberg890ea892013-03-15 17:06:52 -0500816 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817}
818
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200819static u8 get_adv_type(struct hci_dev *hdev)
820{
821 struct pending_cmd *cmd;
822 bool connectable;
823
824 /* If there's a pending mgmt command the flag will not yet have
825 * it's final value, so check for this first.
826 */
827 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
828 if (cmd) {
829 struct mgmt_mode *cp = cmd->param;
830 connectable = !!cp->val;
831 } else {
832 connectable = test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
833 }
834
835 return connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
836}
837
838static void enable_advertising(struct hci_request *req)
839{
840 struct hci_dev *hdev = req->hdev;
841 struct hci_cp_le_set_adv_param cp;
842 u8 enable = 0x01;
843
844 memset(&cp, 0, sizeof(cp));
845 cp.min_interval = __constant_cpu_to_le16(0x0800);
846 cp.max_interval = __constant_cpu_to_le16(0x0800);
847 cp.type = get_adv_type(hdev);
848 cp.own_address_type = hdev->own_addr_type;
849 cp.channel_map = hdev->le_adv_channel_map;
850
851 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
852
853 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
854}
855
856static void disable_advertising(struct hci_request *req)
857{
858 u8 enable = 0x00;
859
860 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
861}
862
Johan Hedberg7d785252011-12-15 00:47:39 +0200863static void service_cache_off(struct work_struct *work)
864{
865 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300866 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500867 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200868
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200869 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200870 return;
871
Johan Hedberg890ea892013-03-15 17:06:52 -0500872 hci_req_init(&req, hdev);
873
Johan Hedberg7d785252011-12-15 00:47:39 +0200874 hci_dev_lock(hdev);
875
Johan Hedberg890ea892013-03-15 17:06:52 -0500876 update_eir(&req);
877 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200878
879 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500880
881 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200882}
883
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200884static void rpa_expired(struct work_struct *work)
885{
886 struct hci_dev *hdev = container_of(work, struct hci_dev,
887 rpa_expired.work);
888 struct hci_request req;
889
890 BT_DBG("");
891
892 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
893
894 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
895 hci_conn_num(hdev, LE_LINK) > 0)
896 return;
897
898 /* The generation of a new RPA and programming it into the
899 * controller happens in the enable_advertising() function.
900 */
901
902 hci_req_init(&req, hdev);
903
904 disable_advertising(&req);
905 enable_advertising(&req);
906
907 hci_req_run(&req, NULL);
908}
909
Johan Hedberg6a919082012-02-28 06:17:26 +0200910static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200911{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200912 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200913 return;
914
Johan Hedberg4f87da82012-03-02 19:55:56 +0200915 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200916 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200917
Johan Hedberg4f87da82012-03-02 19:55:56 +0200918 /* Non-mgmt controlled devices get this bit set
919 * implicitly so that pairing works for them, however
920 * for mgmt we require user-space to explicitly enable
921 * it
922 */
923 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200924}
925
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200926static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300927 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200928{
929 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200930
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200931 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200932
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300933 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200934
Johan Hedberg03811012010-12-08 00:21:06 +0200935 memset(&rp, 0, sizeof(rp));
936
Johan Hedberg03811012010-12-08 00:21:06 +0200937 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200938
939 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200940 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200941
942 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
943 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
944
945 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200946
947 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200948 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200949
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300950 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200951
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200952 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300953 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200954}
955
956static void mgmt_pending_free(struct pending_cmd *cmd)
957{
958 sock_put(cmd->sk);
959 kfree(cmd->param);
960 kfree(cmd);
961}
962
963static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300964 struct hci_dev *hdev, void *data,
965 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200966{
967 struct pending_cmd *cmd;
968
Andre Guedes12b94562012-06-07 19:05:45 -0300969 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200970 if (!cmd)
971 return NULL;
972
973 cmd->opcode = opcode;
974 cmd->index = hdev->id;
975
Andre Guedes12b94562012-06-07 19:05:45 -0300976 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200977 if (!cmd->param) {
978 kfree(cmd);
979 return NULL;
980 }
981
982 if (data)
983 memcpy(cmd->param, data, len);
984
985 cmd->sk = sk;
986 sock_hold(sk);
987
988 list_add(&cmd->list, &hdev->mgmt_pending);
989
990 return cmd;
991}
992
993static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300994 void (*cb)(struct pending_cmd *cmd,
995 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300996 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +0200997{
Andre Guedesa3d09352013-02-01 11:21:30 -0300998 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +0200999
Andre Guedesa3d09352013-02-01 11:21:30 -03001000 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001001 if (opcode > 0 && cmd->opcode != opcode)
1002 continue;
1003
1004 cb(cmd, data);
1005 }
1006}
1007
Johan Hedberg03811012010-12-08 00:21:06 +02001008static void mgmt_pending_remove(struct pending_cmd *cmd)
1009{
1010 list_del(&cmd->list);
1011 mgmt_pending_free(cmd);
1012}
1013
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001014static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001015{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001016 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001017
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001018 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001019 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001020}
1021
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001022static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001023 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001024{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001025 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001026 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001027 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001029 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001030
Johan Hedberga7e80f22013-01-09 16:05:19 +02001031 if (cp->val != 0x00 && cp->val != 0x01)
1032 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1033 MGMT_STATUS_INVALID_PARAMS);
1034
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001035 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001036
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001037 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1038 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1039 MGMT_STATUS_BUSY);
1040 goto failed;
1041 }
1042
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001043 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1044 cancel_delayed_work(&hdev->power_off);
1045
1046 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001047 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1048 data, len);
1049 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001050 goto failed;
1051 }
1052 }
1053
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001054 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001055 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001056 goto failed;
1057 }
1058
Johan Hedberg03811012010-12-08 00:21:06 +02001059 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1060 if (!cmd) {
1061 err = -ENOMEM;
1062 goto failed;
1063 }
1064
1065 if (cp->val)
Johan Hedberg19202572013-01-14 22:33:51 +02001066 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg03811012010-12-08 00:21:06 +02001067 else
Johan Hedberg19202572013-01-14 22:33:51 +02001068 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg03811012010-12-08 00:21:06 +02001069
1070 err = 0;
1071
1072failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001073 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001074 return err;
1075}
1076
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001077static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1078 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001079{
1080 struct sk_buff *skb;
1081 struct mgmt_hdr *hdr;
1082
Andre Guedes790eff42012-06-07 19:05:46 -03001083 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001084 if (!skb)
1085 return -ENOMEM;
1086
1087 hdr = (void *) skb_put(skb, sizeof(*hdr));
1088 hdr->opcode = cpu_to_le16(event);
1089 if (hdev)
1090 hdr->index = cpu_to_le16(hdev->id);
1091 else
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05301092 hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001093 hdr->len = cpu_to_le16(data_len);
1094
1095 if (data)
1096 memcpy(skb_put(skb, data_len), data, data_len);
1097
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001098 /* Time stamp */
1099 __net_timestamp(skb);
1100
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001101 hci_send_to_control(skb, skip_sk);
1102 kfree_skb(skb);
1103
1104 return 0;
1105}
1106
1107static int new_settings(struct hci_dev *hdev, struct sock *skip)
1108{
1109 __le32 ev;
1110
1111 ev = cpu_to_le32(get_current_settings(hdev));
1112
1113 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1114}
1115
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001116struct cmd_lookup {
1117 struct sock *sk;
1118 struct hci_dev *hdev;
1119 u8 mgmt_status;
1120};
1121
1122static void settings_rsp(struct pending_cmd *cmd, void *data)
1123{
1124 struct cmd_lookup *match = data;
1125
1126 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1127
1128 list_del(&cmd->list);
1129
1130 if (match->sk == NULL) {
1131 match->sk = cmd->sk;
1132 sock_hold(match->sk);
1133 }
1134
1135 mgmt_pending_free(cmd);
1136}
1137
1138static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1139{
1140 u8 *status = data;
1141
1142 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1143 mgmt_pending_remove(cmd);
1144}
1145
Johan Hedberge6fe7982013-10-02 15:45:22 +03001146static u8 mgmt_bredr_support(struct hci_dev *hdev)
1147{
1148 if (!lmp_bredr_capable(hdev))
1149 return MGMT_STATUS_NOT_SUPPORTED;
1150 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1151 return MGMT_STATUS_REJECTED;
1152 else
1153 return MGMT_STATUS_SUCCESS;
1154}
1155
1156static u8 mgmt_le_support(struct hci_dev *hdev)
1157{
1158 if (!lmp_le_capable(hdev))
1159 return MGMT_STATUS_NOT_SUPPORTED;
1160 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1161 return MGMT_STATUS_REJECTED;
1162 else
1163 return MGMT_STATUS_SUCCESS;
1164}
1165
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001166static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1167{
1168 struct pending_cmd *cmd;
1169 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001170 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001171 bool changed;
1172
1173 BT_DBG("status 0x%02x", status);
1174
1175 hci_dev_lock(hdev);
1176
1177 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1178 if (!cmd)
1179 goto unlock;
1180
1181 if (status) {
1182 u8 mgmt_err = mgmt_status(status);
1183 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001184 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001185 goto remove_cmd;
1186 }
1187
1188 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001189 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001190 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1191 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001192
1193 if (hdev->discov_timeout > 0) {
1194 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1195 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1196 to);
1197 }
1198 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001199 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1200 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001201 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001202
1203 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1204
1205 if (changed)
1206 new_settings(hdev, cmd->sk);
1207
Marcel Holtmann970ba522013-10-15 06:33:57 -07001208 /* When the discoverable mode gets changed, make sure
1209 * that class of device has the limited discoverable
1210 * bit correctly set.
1211 */
1212 hci_req_init(&req, hdev);
1213 update_class(&req);
1214 hci_req_run(&req, NULL);
1215
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001216remove_cmd:
1217 mgmt_pending_remove(cmd);
1218
1219unlock:
1220 hci_dev_unlock(hdev);
1221}
1222
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001223static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001224 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001225{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001226 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001227 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001228 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001229 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001230 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001231 int err;
1232
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001233 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001234
Johan Hedberg9a43e252013-10-20 19:00:07 +03001235 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1236 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001237 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001238 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001239
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001240 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001241 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1242 MGMT_STATUS_INVALID_PARAMS);
1243
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001244 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001245
1246 /* Disabling discoverable requires that no timeout is set,
1247 * and enabling limited discoverable requires a timeout.
1248 */
1249 if ((cp->val == 0x00 && timeout > 0) ||
1250 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001251 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001252 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001253
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001254 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001255
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001256 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001257 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001258 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001259 goto failed;
1260 }
1261
1262 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001263 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001264 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001265 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001266 goto failed;
1267 }
1268
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001269 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001270 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001271 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001272 goto failed;
1273 }
1274
1275 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001276 bool changed = false;
1277
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001278 /* Setting limited discoverable when powered off is
1279 * not a valid operation since it requires a timeout
1280 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1281 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001282 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1283 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1284 changed = true;
1285 }
1286
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001287 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001288 if (err < 0)
1289 goto failed;
1290
1291 if (changed)
1292 err = new_settings(hdev, sk);
1293
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001294 goto failed;
1295 }
1296
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001297 /* If the current mode is the same, then just update the timeout
1298 * value with the new value. And if only the timeout gets updated,
1299 * then no need for any HCI transactions.
1300 */
1301 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1302 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1303 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001304 cancel_delayed_work(&hdev->discov_off);
1305 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001306
Marcel Holtmann36261542013-10-15 08:28:51 -07001307 if (cp->val && hdev->discov_timeout > 0) {
1308 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001309 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001310 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001311 }
1312
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001313 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001314 goto failed;
1315 }
1316
1317 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1318 if (!cmd) {
1319 err = -ENOMEM;
1320 goto failed;
1321 }
1322
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001323 /* Cancel any potential discoverable timeout that might be
1324 * still active and store new timeout value. The arming of
1325 * the timeout happens in the complete handler.
1326 */
1327 cancel_delayed_work(&hdev->discov_off);
1328 hdev->discov_timeout = timeout;
1329
Johan Hedbergb456f872013-10-19 23:38:22 +03001330 /* Limited discoverable mode */
1331 if (cp->val == 0x02)
1332 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1333 else
1334 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1335
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001336 hci_req_init(&req, hdev);
1337
Johan Hedberg9a43e252013-10-20 19:00:07 +03001338 /* The procedure for LE-only controllers is much simpler - just
1339 * update the advertising data.
1340 */
1341 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1342 goto update_ad;
1343
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001344 scan = SCAN_PAGE;
1345
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001346 if (cp->val) {
1347 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001348
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001349 if (cp->val == 0x02) {
1350 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001351 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001352 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1353 hci_cp.iac_lap[1] = 0x8b;
1354 hci_cp.iac_lap[2] = 0x9e;
1355 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1356 hci_cp.iac_lap[4] = 0x8b;
1357 hci_cp.iac_lap[5] = 0x9e;
1358 } else {
1359 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001360 hci_cp.num_iac = 1;
1361 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1362 hci_cp.iac_lap[1] = 0x8b;
1363 hci_cp.iac_lap[2] = 0x9e;
1364 }
1365
1366 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1367 (hci_cp.num_iac * 3) + 1, &hci_cp);
1368
1369 scan |= SCAN_INQUIRY;
1370 } else {
1371 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1372 }
1373
1374 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001375
Johan Hedberg9a43e252013-10-20 19:00:07 +03001376update_ad:
1377 update_adv_data(&req);
1378
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001379 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001380 if (err < 0)
1381 mgmt_pending_remove(cmd);
1382
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001383failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001384 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001385 return err;
1386}
1387
Johan Hedberg406d7802013-03-15 17:07:09 -05001388static void write_fast_connectable(struct hci_request *req, bool enable)
1389{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001390 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001391 struct hci_cp_write_page_scan_activity acp;
1392 u8 type;
1393
Johan Hedberg547003b2013-10-21 16:51:53 +03001394 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1395 return;
1396
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001397 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1398 return;
1399
Johan Hedberg406d7802013-03-15 17:07:09 -05001400 if (enable) {
1401 type = PAGE_SCAN_TYPE_INTERLACED;
1402
1403 /* 160 msec page scan interval */
1404 acp.interval = __constant_cpu_to_le16(0x0100);
1405 } else {
1406 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1407
1408 /* default 1.28 sec page scan */
1409 acp.interval = __constant_cpu_to_le16(0x0800);
1410 }
1411
1412 acp.window = __constant_cpu_to_le16(0x0012);
1413
Johan Hedbergbd98b992013-03-15 17:07:13 -05001414 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1415 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1416 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1417 sizeof(acp), &acp);
1418
1419 if (hdev->page_scan_type != type)
1420 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001421}
1422
Johan Hedberg2b76f452013-03-15 17:07:04 -05001423static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1424{
1425 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001426 struct mgmt_mode *cp;
1427 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001428
1429 BT_DBG("status 0x%02x", status);
1430
1431 hci_dev_lock(hdev);
1432
1433 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1434 if (!cmd)
1435 goto unlock;
1436
Johan Hedberg37438c12013-10-14 16:20:05 +03001437 if (status) {
1438 u8 mgmt_err = mgmt_status(status);
1439 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1440 goto remove_cmd;
1441 }
1442
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001443 cp = cmd->param;
1444 if (cp->val)
1445 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1446 else
1447 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1448
Johan Hedberg2b76f452013-03-15 17:07:04 -05001449 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1450
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001451 if (changed)
1452 new_settings(hdev, cmd->sk);
1453
Johan Hedberg37438c12013-10-14 16:20:05 +03001454remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001455 mgmt_pending_remove(cmd);
1456
1457unlock:
1458 hci_dev_unlock(hdev);
1459}
1460
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001461static int set_connectable_update_settings(struct hci_dev *hdev,
1462 struct sock *sk, u8 val)
1463{
1464 bool changed = false;
1465 int err;
1466
1467 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1468 changed = true;
1469
1470 if (val) {
1471 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1472 } else {
1473 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1474 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1475 }
1476
1477 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1478 if (err < 0)
1479 return err;
1480
1481 if (changed)
1482 return new_settings(hdev, sk);
1483
1484 return 0;
1485}
1486
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001487static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001488 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001489{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001490 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001491 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001492 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001493 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001494 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001495
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001496 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001497
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001498 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1499 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001500 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001501 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001502
Johan Hedberga7e80f22013-01-09 16:05:19 +02001503 if (cp->val != 0x00 && cp->val != 0x01)
1504 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1505 MGMT_STATUS_INVALID_PARAMS);
1506
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001507 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001508
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001509 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001510 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001511 goto failed;
1512 }
1513
1514 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001515 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001516 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001517 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001518 goto failed;
1519 }
1520
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001521 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1522 if (!cmd) {
1523 err = -ENOMEM;
1524 goto failed;
1525 }
1526
Johan Hedberg2b76f452013-03-15 17:07:04 -05001527 hci_req_init(&req, hdev);
1528
Johan Hedberg9a43e252013-10-20 19:00:07 +03001529 /* If BR/EDR is not enabled and we disable advertising as a
1530 * by-product of disabling connectable, we need to update the
1531 * advertising flags.
1532 */
1533 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1534 if (!cp->val) {
1535 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1536 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1537 }
1538 update_adv_data(&req);
1539 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001540 if (cp->val) {
1541 scan = SCAN_PAGE;
1542 } else {
1543 scan = 0;
1544
1545 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001546 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001547 cancel_delayed_work(&hdev->discov_off);
1548 }
1549
1550 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1551 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001552
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001553 /* If we're going from non-connectable to connectable or
1554 * vice-versa when fast connectable is enabled ensure that fast
1555 * connectable gets disabled. write_fast_connectable won't do
1556 * anything if the page scan parameters are already what they
1557 * should be.
1558 */
1559 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001560 write_fast_connectable(&req, false);
1561
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001562 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1563 hci_conn_num(hdev, LE_LINK) == 0) {
1564 disable_advertising(&req);
1565 enable_advertising(&req);
1566 }
1567
Johan Hedberg2b76f452013-03-15 17:07:04 -05001568 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001569 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001570 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001571 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001572 err = set_connectable_update_settings(hdev, sk,
1573 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001574 goto failed;
1575 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001576
1577failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001578 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001579 return err;
1580}
1581
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001582static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001583 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001584{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001585 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001586 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001587 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001589 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001590
Johan Hedberga7e80f22013-01-09 16:05:19 +02001591 if (cp->val != 0x00 && cp->val != 0x01)
1592 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1593 MGMT_STATUS_INVALID_PARAMS);
1594
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001595 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001596
1597 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001598 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001599 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001600 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001601
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001602 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001603 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001604 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001605
Marcel Holtmann55594352013-10-06 16:11:57 -07001606 if (changed)
1607 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001608
Marcel Holtmann55594352013-10-06 16:11:57 -07001609unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001610 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001611 return err;
1612}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001613
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001614static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1615 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001616{
1617 struct mgmt_mode *cp = data;
1618 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001619 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001620 int err;
1621
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001622 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001623
Johan Hedberge6fe7982013-10-02 15:45:22 +03001624 status = mgmt_bredr_support(hdev);
1625 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001626 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001627 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001628
Johan Hedberga7e80f22013-01-09 16:05:19 +02001629 if (cp->val != 0x00 && cp->val != 0x01)
1630 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1631 MGMT_STATUS_INVALID_PARAMS);
1632
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001633 hci_dev_lock(hdev);
1634
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001635 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001636 bool changed = false;
1637
1638 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001639 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001640 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1641 changed = true;
1642 }
1643
1644 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1645 if (err < 0)
1646 goto failed;
1647
1648 if (changed)
1649 err = new_settings(hdev, sk);
1650
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001651 goto failed;
1652 }
1653
1654 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001655 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001656 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001657 goto failed;
1658 }
1659
1660 val = !!cp->val;
1661
1662 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1663 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1664 goto failed;
1665 }
1666
1667 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1668 if (!cmd) {
1669 err = -ENOMEM;
1670 goto failed;
1671 }
1672
1673 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1674 if (err < 0) {
1675 mgmt_pending_remove(cmd);
1676 goto failed;
1677 }
1678
1679failed:
1680 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001681 return err;
1682}
1683
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001684static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001685{
1686 struct mgmt_mode *cp = data;
1687 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001688 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001689 int err;
1690
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001691 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001692
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001693 status = mgmt_bredr_support(hdev);
1694 if (status)
1695 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1696
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001697 if (!lmp_ssp_capable(hdev))
1698 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1699 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001700
Johan Hedberga7e80f22013-01-09 16:05:19 +02001701 if (cp->val != 0x00 && cp->val != 0x01)
1702 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1703 MGMT_STATUS_INVALID_PARAMS);
1704
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001705 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001706
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001707 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001708 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001709
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001710 if (cp->val) {
1711 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1712 &hdev->dev_flags);
1713 } else {
1714 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1715 &hdev->dev_flags);
1716 if (!changed)
1717 changed = test_and_clear_bit(HCI_HS_ENABLED,
1718 &hdev->dev_flags);
1719 else
1720 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001721 }
1722
1723 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1724 if (err < 0)
1725 goto failed;
1726
1727 if (changed)
1728 err = new_settings(hdev, sk);
1729
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001730 goto failed;
1731 }
1732
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001733 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1734 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001735 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1736 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001737 goto failed;
1738 }
1739
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001740 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001741 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1742 goto failed;
1743 }
1744
1745 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1746 if (!cmd) {
1747 err = -ENOMEM;
1748 goto failed;
1749 }
1750
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001751 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001752 if (err < 0) {
1753 mgmt_pending_remove(cmd);
1754 goto failed;
1755 }
1756
1757failed:
1758 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001759 return err;
1760}
1761
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001762static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001763{
1764 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001765 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001766 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001767 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001768
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001769 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001770
Johan Hedberge6fe7982013-10-02 15:45:22 +03001771 status = mgmt_bredr_support(hdev);
1772 if (status)
1773 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001774
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001775 if (!lmp_ssp_capable(hdev))
1776 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1777 MGMT_STATUS_NOT_SUPPORTED);
1778
1779 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1780 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1781 MGMT_STATUS_REJECTED);
1782
Johan Hedberga7e80f22013-01-09 16:05:19 +02001783 if (cp->val != 0x00 && cp->val != 0x01)
1784 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1785 MGMT_STATUS_INVALID_PARAMS);
1786
Marcel Holtmannee392692013-10-01 22:59:23 -07001787 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001788
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001789 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001790 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001791 } else {
1792 if (hdev_is_powered(hdev)) {
1793 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1794 MGMT_STATUS_REJECTED);
1795 goto unlock;
1796 }
1797
Marcel Holtmannee392692013-10-01 22:59:23 -07001798 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001799 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001800
1801 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1802 if (err < 0)
1803 goto unlock;
1804
1805 if (changed)
1806 err = new_settings(hdev, sk);
1807
1808unlock:
1809 hci_dev_unlock(hdev);
1810 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001811}
1812
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001813static void le_enable_complete(struct hci_dev *hdev, u8 status)
1814{
1815 struct cmd_lookup match = { NULL, hdev };
1816
1817 if (status) {
1818 u8 mgmt_err = mgmt_status(status);
1819
1820 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1821 &mgmt_err);
1822 return;
1823 }
1824
1825 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1826
1827 new_settings(hdev, match.sk);
1828
1829 if (match.sk)
1830 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001831
1832 /* Make sure the controller has a good default for
1833 * advertising data. Restrict the update to when LE
1834 * has actually been enabled. During power on, the
1835 * update in powered_update_hci will take care of it.
1836 */
1837 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1838 struct hci_request req;
1839
1840 hci_dev_lock(hdev);
1841
1842 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001843 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001844 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001845 hci_req_run(&req, NULL);
1846
1847 hci_dev_unlock(hdev);
1848 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001849}
1850
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001851static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001852{
1853 struct mgmt_mode *cp = data;
1854 struct hci_cp_write_le_host_supported hci_cp;
1855 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001856 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001857 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001858 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001859
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001860 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001861
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001862 if (!lmp_le_capable(hdev))
1863 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1864 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001865
Johan Hedberga7e80f22013-01-09 16:05:19 +02001866 if (cp->val != 0x00 && cp->val != 0x01)
1867 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1868 MGMT_STATUS_INVALID_PARAMS);
1869
Johan Hedbergc73eee92013-04-19 18:35:21 +03001870 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03001871 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03001872 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1873 MGMT_STATUS_REJECTED);
1874
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001875 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001876
1877 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001878 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001879
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001880 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02001881 bool changed = false;
1882
1883 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1884 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1885 changed = true;
1886 }
1887
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02001888 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
1889 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03001890 changed = true;
1891 }
1892
Johan Hedberg06199cf2012-02-22 16:37:11 +02001893 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1894 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08001895 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001896
1897 if (changed)
1898 err = new_settings(hdev, sk);
1899
Johan Hedberg1de028c2012-02-29 19:55:35 -08001900 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001901 }
1902
Johan Hedberg4375f102013-09-25 13:26:10 +03001903 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
1904 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001905 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001906 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001907 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001908 }
1909
1910 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
1911 if (!cmd) {
1912 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08001913 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001914 }
1915
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001916 hci_req_init(&req, hdev);
1917
Johan Hedberg06199cf2012-02-22 16:37:11 +02001918 memset(&hci_cp, 0, sizeof(hci_cp));
1919
1920 if (val) {
1921 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001922 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001923 } else {
1924 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1925 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001926 }
1927
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001928 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
1929 &hci_cp);
1930
1931 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05301932 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001933 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001934
Johan Hedberg1de028c2012-02-29 19:55:35 -08001935unlock:
1936 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001937 return err;
1938}
1939
Johan Hedberg0cab9c82013-03-15 17:06:54 -05001940/* This is a helper function to test for pending mgmt commands that can
1941 * cause CoD or EIR HCI commands. We can only allow one such pending
1942 * mgmt command at a time since otherwise we cannot easily track what
1943 * the current values are, will be, and based on that calculate if a new
1944 * HCI command needs to be sent and if yes with what value.
1945 */
1946static bool pending_eir_or_class(struct hci_dev *hdev)
1947{
1948 struct pending_cmd *cmd;
1949
1950 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
1951 switch (cmd->opcode) {
1952 case MGMT_OP_ADD_UUID:
1953 case MGMT_OP_REMOVE_UUID:
1954 case MGMT_OP_SET_DEV_CLASS:
1955 case MGMT_OP_SET_POWERED:
1956 return true;
1957 }
1958 }
1959
1960 return false;
1961}
1962
Johan Hedberg83be8ec2013-01-27 00:31:29 +02001963static const u8 bluetooth_base_uuid[] = {
1964 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
1965 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1966};
1967
1968static u8 get_uuid_size(const u8 *uuid)
1969{
1970 u32 val;
1971
1972 if (memcmp(uuid, bluetooth_base_uuid, 12))
1973 return 128;
1974
1975 val = get_unaligned_le32(&uuid[12]);
1976 if (val > 0xffff)
1977 return 32;
1978
1979 return 16;
1980}
1981
Johan Hedberg92da6092013-03-15 17:06:55 -05001982static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
1983{
1984 struct pending_cmd *cmd;
1985
1986 hci_dev_lock(hdev);
1987
1988 cmd = mgmt_pending_find(mgmt_op, hdev);
1989 if (!cmd)
1990 goto unlock;
1991
1992 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
1993 hdev->dev_class, 3);
1994
1995 mgmt_pending_remove(cmd);
1996
1997unlock:
1998 hci_dev_unlock(hdev);
1999}
2000
2001static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2002{
2003 BT_DBG("status 0x%02x", status);
2004
2005 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2006}
2007
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002008static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002009{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002010 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002011 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002012 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002013 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002014 int err;
2015
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002016 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002017
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002018 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002019
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002020 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002021 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002022 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002023 goto failed;
2024 }
2025
Andre Guedes92c4c202012-06-07 19:05:44 -03002026 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002027 if (!uuid) {
2028 err = -ENOMEM;
2029 goto failed;
2030 }
2031
2032 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002033 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002034 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002035
Johan Hedbergde66aa62013-01-27 00:31:27 +02002036 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002037
Johan Hedberg890ea892013-03-15 17:06:52 -05002038 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002039
Johan Hedberg890ea892013-03-15 17:06:52 -05002040 update_class(&req);
2041 update_eir(&req);
2042
Johan Hedberg92da6092013-03-15 17:06:55 -05002043 err = hci_req_run(&req, add_uuid_complete);
2044 if (err < 0) {
2045 if (err != -ENODATA)
2046 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002047
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002048 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002049 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002050 goto failed;
2051 }
2052
2053 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002054 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002055 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002056 goto failed;
2057 }
2058
2059 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002060
2061failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002062 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002063 return err;
2064}
2065
Johan Hedberg24b78d02012-02-23 23:24:30 +02002066static bool enable_service_cache(struct hci_dev *hdev)
2067{
2068 if (!hdev_is_powered(hdev))
2069 return false;
2070
2071 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002072 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2073 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002074 return true;
2075 }
2076
2077 return false;
2078}
2079
Johan Hedberg92da6092013-03-15 17:06:55 -05002080static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2081{
2082 BT_DBG("status 0x%02x", status);
2083
2084 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2085}
2086
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002087static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002088 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002089{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002090 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002091 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002092 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002093 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 -05002094 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002095 int err, found;
2096
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002097 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002098
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002099 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002100
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002101 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002102 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002103 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002104 goto unlock;
2105 }
2106
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002107 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002108 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002109
Johan Hedberg24b78d02012-02-23 23:24:30 +02002110 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002111 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002112 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002113 goto unlock;
2114 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002115
Johan Hedberg9246a862012-02-23 21:33:16 +02002116 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002117 }
2118
2119 found = 0;
2120
Johan Hedberg056341c2013-01-27 00:31:30 +02002121 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002122 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2123 continue;
2124
2125 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002126 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002127 found++;
2128 }
2129
2130 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002131 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002132 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002133 goto unlock;
2134 }
2135
Johan Hedberg9246a862012-02-23 21:33:16 +02002136update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002137 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002138
Johan Hedberg890ea892013-03-15 17:06:52 -05002139 update_class(&req);
2140 update_eir(&req);
2141
Johan Hedberg92da6092013-03-15 17:06:55 -05002142 err = hci_req_run(&req, remove_uuid_complete);
2143 if (err < 0) {
2144 if (err != -ENODATA)
2145 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002148 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002149 goto unlock;
2150 }
2151
2152 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002153 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002154 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002155 goto unlock;
2156 }
2157
2158 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002159
2160unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002161 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002162 return err;
2163}
2164
Johan Hedberg92da6092013-03-15 17:06:55 -05002165static void set_class_complete(struct hci_dev *hdev, u8 status)
2166{
2167 BT_DBG("status 0x%02x", status);
2168
2169 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2170}
2171
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002172static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002173 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002174{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002175 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002176 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002177 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002178 int err;
2179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002180 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002181
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002182 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002183 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2184 MGMT_STATUS_NOT_SUPPORTED);
2185
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002186 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002187
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002188 if (pending_eir_or_class(hdev)) {
2189 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2190 MGMT_STATUS_BUSY);
2191 goto unlock;
2192 }
2193
2194 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2195 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2196 MGMT_STATUS_INVALID_PARAMS);
2197 goto unlock;
2198 }
2199
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002200 hdev->major_class = cp->major;
2201 hdev->minor_class = cp->minor;
2202
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002203 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002204 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002205 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002206 goto unlock;
2207 }
2208
Johan Hedberg890ea892013-03-15 17:06:52 -05002209 hci_req_init(&req, hdev);
2210
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002211 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002212 hci_dev_unlock(hdev);
2213 cancel_delayed_work_sync(&hdev->service_cache);
2214 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002215 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002216 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002217
Johan Hedberg890ea892013-03-15 17:06:52 -05002218 update_class(&req);
2219
Johan Hedberg92da6092013-03-15 17:06:55 -05002220 err = hci_req_run(&req, set_class_complete);
2221 if (err < 0) {
2222 if (err != -ENODATA)
2223 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002224
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002225 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002226 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002227 goto unlock;
2228 }
2229
2230 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002231 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002232 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002233 goto unlock;
2234 }
2235
2236 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002237
Johan Hedbergb5235a62012-02-21 14:32:24 +02002238unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002239 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002240 return err;
2241}
2242
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002243static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002244 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002245{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002246 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002247 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002248 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002249 int i;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002250
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002251 BT_DBG("request for %s", hdev->name);
2252
2253 if (!lmp_bredr_capable(hdev))
2254 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2255 MGMT_STATUS_NOT_SUPPORTED);
2256
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002257 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002258
Johan Hedberg86742e12011-11-07 23:13:38 +02002259 expected_len = sizeof(*cp) + key_count *
2260 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002261 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002262 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002263 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002264 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002265 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002266 }
2267
Johan Hedberg4ae14302013-01-20 14:27:13 +02002268 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2269 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2270 MGMT_STATUS_INVALID_PARAMS);
2271
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002272 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002273 key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002274
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002275 for (i = 0; i < key_count; i++) {
2276 struct mgmt_link_key_info *key = &cp->keys[i];
2277
Marcel Holtmann8e991132014-01-10 02:07:25 -08002278 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002279 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2280 MGMT_STATUS_INVALID_PARAMS);
2281 }
2282
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002283 hci_dev_lock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002284
2285 hci_link_keys_clear(hdev);
2286
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002287 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002288 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002289 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002290 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2291
2292 if (changed)
2293 new_settings(hdev, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002294
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002295 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002296 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002297
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002298 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002299 key->type, key->pin_len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002300 }
2301
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002302 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002303
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002304 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002305
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002306 return 0;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002307}
2308
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002309static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002310 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002311{
2312 struct mgmt_ev_device_unpaired ev;
2313
2314 bacpy(&ev.addr.bdaddr, bdaddr);
2315 ev.addr.type = addr_type;
2316
2317 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002318 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002319}
2320
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002321static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002322 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002323{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002324 struct mgmt_cp_unpair_device *cp = data;
2325 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002326 struct hci_cp_disconnect dc;
2327 struct pending_cmd *cmd;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002328 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002329 int err;
2330
Johan Hedberga8a1d192011-11-10 15:54:38 +02002331 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002332 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2333 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002334
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002335 if (!bdaddr_type_is_valid(cp->addr.type))
2336 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2337 MGMT_STATUS_INVALID_PARAMS,
2338 &rp, sizeof(rp));
2339
Johan Hedberg118da702013-01-20 14:27:20 +02002340 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2341 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2342 MGMT_STATUS_INVALID_PARAMS,
2343 &rp, sizeof(rp));
2344
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002345 hci_dev_lock(hdev);
2346
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002347 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002348 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002349 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002350 goto unlock;
2351 }
2352
Johan Hedberge0b2b272014-02-18 17:14:31 +02002353 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002354 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002355 } else {
2356 u8 addr_type;
2357
2358 if (cp->addr.type == BDADDR_LE_PUBLIC)
2359 addr_type = ADDR_LE_DEV_PUBLIC;
2360 else
2361 addr_type = ADDR_LE_DEV_RANDOM;
2362
Johan Hedberga7ec7332014-02-18 17:14:35 +02002363 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2364
Johan Hedberge0b2b272014-02-18 17:14:31 +02002365 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2366 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002367
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002368 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002369 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002370 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002371 goto unlock;
2372 }
2373
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002374 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002375 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002376 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002377 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002378 else
2379 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002380 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002381 } else {
2382 conn = NULL;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002383 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002384
Johan Hedberga8a1d192011-11-10 15:54:38 +02002385 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002386 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002387 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002388 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002389 goto unlock;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002390 }
2391
Johan Hedberg124f6e32012-02-09 13:50:12 +02002392 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002393 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002394 if (!cmd) {
2395 err = -ENOMEM;
2396 goto unlock;
2397 }
2398
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002399 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002400 dc.reason = 0x13; /* Remote User Terminated Connection */
2401 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2402 if (err < 0)
2403 mgmt_pending_remove(cmd);
2404
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002405unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002406 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002407 return err;
2408}
2409
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002410static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002411 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002412{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002413 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002414 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002415 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002416 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002417 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002418 int err;
2419
2420 BT_DBG("");
2421
Johan Hedberg06a63b12013-01-20 14:27:21 +02002422 memset(&rp, 0, sizeof(rp));
2423 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2424 rp.addr.type = cp->addr.type;
2425
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002426 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002427 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2428 MGMT_STATUS_INVALID_PARAMS,
2429 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002430
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002431 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002432
2433 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002434 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2435 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002436 goto failed;
2437 }
2438
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002439 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002440 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2441 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002442 goto failed;
2443 }
2444
Andre Guedes591f47f2012-04-24 21:02:49 -03002445 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002446 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2447 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002448 else
2449 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002450
Vishal Agarwalf9607272012-06-13 05:32:43 +05302451 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002452 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2453 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002454 goto failed;
2455 }
2456
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002457 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002458 if (!cmd) {
2459 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002460 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002461 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002462
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002463 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002464 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002465
2466 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2467 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002468 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002469
2470failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002471 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002472 return err;
2473}
2474
Andre Guedes57c14772012-04-24 21:02:50 -03002475static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002476{
2477 switch (link_type) {
2478 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002479 switch (addr_type) {
2480 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002481 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002482
Johan Hedberg48264f02011-11-09 13:58:58 +02002483 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002484 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002485 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002486 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002487
Johan Hedberg4c659c32011-11-07 23:13:39 +02002488 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002489 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002490 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002491 }
2492}
2493
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002494static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2495 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002496{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002497 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002498 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002499 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002500 int err;
2501 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002502
2503 BT_DBG("");
2504
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002505 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002506
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002507 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002508 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002509 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002510 goto unlock;
2511 }
2512
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002513 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002514 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2515 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002516 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002517 }
2518
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002519 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002520 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002521 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002522 err = -ENOMEM;
2523 goto unlock;
2524 }
2525
Johan Hedberg2784eb42011-01-21 13:56:35 +02002526 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002527 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002528 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2529 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002530 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002531 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002532 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002533 continue;
2534 i++;
2535 }
2536
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002537 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002538
Johan Hedberg4c659c32011-11-07 23:13:39 +02002539 /* Recalculate length in case of filtered SCO connections, etc */
2540 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002541
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002542 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002543 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002544
Johan Hedberga38528f2011-01-22 06:46:43 +02002545 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002546
2547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002549 return err;
2550}
2551
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002552static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002553 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002554{
2555 struct pending_cmd *cmd;
2556 int err;
2557
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002558 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002559 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002560 if (!cmd)
2561 return -ENOMEM;
2562
Johan Hedbergd8457692012-02-17 14:24:57 +02002563 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002564 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002565 if (err < 0)
2566 mgmt_pending_remove(cmd);
2567
2568 return err;
2569}
2570
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002571static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002572 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002573{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002574 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002575 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002576 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002577 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002578 int err;
2579
2580 BT_DBG("");
2581
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002582 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002583
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002584 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002585 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002586 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002587 goto failed;
2588 }
2589
Johan Hedbergd8457692012-02-17 14:24:57 +02002590 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002591 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002593 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002594 goto failed;
2595 }
2596
2597 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002598 struct mgmt_cp_pin_code_neg_reply ncp;
2599
2600 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002601
2602 BT_ERR("PIN code is not 16 bytes long");
2603
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002604 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002605 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002606 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002607 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002608
2609 goto failed;
2610 }
2611
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002612 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002613 if (!cmd) {
2614 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002615 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002616 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002617
Johan Hedbergd8457692012-02-17 14:24:57 +02002618 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002619 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002620 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002621
2622 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2623 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002624 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002625
2626failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002627 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002628 return err;
2629}
2630
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002631static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2632 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002633{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002634 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002635
2636 BT_DBG("");
2637
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002638 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002639
2640 hdev->io_capability = cp->io_capability;
2641
2642 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002643 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002644
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002645 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002646
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002647 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2648 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002649}
2650
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002651static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002652{
2653 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002654 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002655
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002656 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002657 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2658 continue;
2659
Johan Hedberge9a416b2011-02-19 12:05:56 -03002660 if (cmd->user_data != conn)
2661 continue;
2662
2663 return cmd;
2664 }
2665
2666 return NULL;
2667}
2668
2669static void pairing_complete(struct pending_cmd *cmd, u8 status)
2670{
2671 struct mgmt_rp_pair_device rp;
2672 struct hci_conn *conn = cmd->user_data;
2673
Johan Hedbergba4e5642011-11-11 00:07:34 +02002674 bacpy(&rp.addr.bdaddr, &conn->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002675 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002676
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002677 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002678 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002679
2680 /* So we don't get further callbacks for this connection */
2681 conn->connect_cfm_cb = NULL;
2682 conn->security_cfm_cb = NULL;
2683 conn->disconn_cfm_cb = NULL;
2684
David Herrmann76a68ba2013-04-06 20:28:37 +02002685 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002686
Johan Hedberga664b5b2011-02-19 12:06:02 -03002687 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002688}
2689
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002690void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2691{
2692 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2693 struct pending_cmd *cmd;
2694
2695 cmd = find_pairing(conn);
2696 if (cmd)
2697 pairing_complete(cmd, status);
2698}
2699
Johan Hedberge9a416b2011-02-19 12:05:56 -03002700static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2701{
2702 struct pending_cmd *cmd;
2703
2704 BT_DBG("status %u", status);
2705
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002706 cmd = find_pairing(conn);
2707 if (!cmd)
2708 BT_DBG("Unable to find a pending command");
2709 else
Johan Hedberge2113262012-02-18 15:20:03 +02002710 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002711}
2712
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002713static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302714{
2715 struct pending_cmd *cmd;
2716
2717 BT_DBG("status %u", status);
2718
2719 if (!status)
2720 return;
2721
2722 cmd = find_pairing(conn);
2723 if (!cmd)
2724 BT_DBG("Unable to find a pending command");
2725 else
2726 pairing_complete(cmd, mgmt_status(status));
2727}
2728
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002729static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002730 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002731{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002732 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002733 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002734 struct pending_cmd *cmd;
2735 u8 sec_level, auth_type;
2736 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002737 int err;
2738
2739 BT_DBG("");
2740
Szymon Jancf950a30e2013-01-18 12:48:07 +01002741 memset(&rp, 0, sizeof(rp));
2742 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2743 rp.addr.type = cp->addr.type;
2744
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002745 if (!bdaddr_type_is_valid(cp->addr.type))
2746 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2747 MGMT_STATUS_INVALID_PARAMS,
2748 &rp, sizeof(rp));
2749
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002750 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002751
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002752 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002753 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2754 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002755 goto unlock;
2756 }
2757
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002758 sec_level = BT_SECURITY_MEDIUM;
2759 if (cp->io_cap == 0x03)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002760 auth_type = HCI_AT_DEDICATED_BONDING;
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002761 else
Johan Hedberge9a416b2011-02-19 12:05:56 -03002762 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002763
Andre Guedes591f47f2012-04-24 21:02:49 -03002764 if (cp->addr.type == BDADDR_BREDR)
Andre Guedesb12f62c2012-04-24 21:02:54 -03002765 conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr,
2766 cp->addr.type, sec_level, auth_type);
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002767 else
Andre Guedesb12f62c2012-04-24 21:02:54 -03002768 conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr,
2769 cp->addr.type, sec_level, auth_type);
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002770
Ville Tervo30e76272011-02-22 16:10:53 -03002771 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002772 int status;
2773
2774 if (PTR_ERR(conn) == -EBUSY)
2775 status = MGMT_STATUS_BUSY;
2776 else
2777 status = MGMT_STATUS_CONNECT_FAILED;
2778
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002779 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002780 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002781 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002782 goto unlock;
2783 }
2784
2785 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002786 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002787 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002788 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002789 goto unlock;
2790 }
2791
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002792 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002793 if (!cmd) {
2794 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002795 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002796 goto unlock;
2797 }
2798
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002799 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002800 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002801 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002802 conn->security_cfm_cb = pairing_complete_cb;
2803 conn->disconn_cfm_cb = pairing_complete_cb;
2804 } else {
2805 conn->connect_cfm_cb = le_pairing_complete_cb;
2806 conn->security_cfm_cb = le_pairing_complete_cb;
2807 conn->disconn_cfm_cb = le_pairing_complete_cb;
2808 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002809
Johan Hedberge9a416b2011-02-19 12:05:56 -03002810 conn->io_capability = cp->io_cap;
2811 cmd->user_data = conn;
2812
2813 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002814 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002815 pairing_complete(cmd, 0);
2816
2817 err = 0;
2818
2819unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002820 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002821 return err;
2822}
2823
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002824static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2825 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002826{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002827 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002828 struct pending_cmd *cmd;
2829 struct hci_conn *conn;
2830 int err;
2831
2832 BT_DBG("");
2833
Johan Hedberg28424702012-02-02 04:02:29 +02002834 hci_dev_lock(hdev);
2835
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002836 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002837 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002838 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002839 goto unlock;
2840 }
2841
Johan Hedberg28424702012-02-02 04:02:29 +02002842 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2843 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002844 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002845 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002846 goto unlock;
2847 }
2848
2849 conn = cmd->user_data;
2850
2851 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002852 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002853 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002854 goto unlock;
2855 }
2856
2857 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2858
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002859 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002860 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02002861unlock:
2862 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02002863 return err;
2864}
2865
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002866static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05002867 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002868 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03002869{
Johan Hedberga5c29682011-02-19 12:05:57 -03002870 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08002871 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002872 int err;
2873
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002874 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02002875
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002876 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002877 err = cmd_complete(sk, hdev->id, mgmt_op,
2878 MGMT_STATUS_NOT_POWERED, addr,
2879 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08002880 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002881 }
2882
Johan Hedberg1707c602013-03-15 17:07:15 -05002883 if (addr->type == BDADDR_BREDR)
2884 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02002885 else
Johan Hedberg1707c602013-03-15 17:07:15 -05002886 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08002887
Johan Hedberg272d90d2012-02-09 15:26:12 +02002888 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002889 err = cmd_complete(sk, hdev->id, mgmt_op,
2890 MGMT_STATUS_NOT_CONNECTED, addr,
2891 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02002892 goto done;
2893 }
2894
Johan Hedberg1707c602013-03-15 17:07:15 -05002895 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08002896 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08002897 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08002898
Brian Gix5fe57d92011-12-21 16:12:13 -08002899 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002900 err = cmd_complete(sk, hdev->id, mgmt_op,
2901 MGMT_STATUS_SUCCESS, addr,
2902 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08002903 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002904 err = cmd_complete(sk, hdev->id, mgmt_op,
2905 MGMT_STATUS_FAILED, addr,
2906 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08002907
Brian Gix47c15e22011-11-16 13:53:14 -08002908 goto done;
2909 }
2910
Johan Hedberg1707c602013-03-15 17:07:15 -05002911 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03002912 if (!cmd) {
2913 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08002914 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002915 }
2916
Brian Gix0df4c182011-11-16 13:53:13 -08002917 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08002918 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
2919 struct hci_cp_user_passkey_reply cp;
2920
Johan Hedberg1707c602013-03-15 17:07:15 -05002921 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08002922 cp.passkey = passkey;
2923 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
2924 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05002925 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
2926 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08002927
Johan Hedberga664b5b2011-02-19 12:06:02 -03002928 if (err < 0)
2929 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03002930
Brian Gix0df4c182011-11-16 13:53:13 -08002931done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002932 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03002933 return err;
2934}
2935
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05302936static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
2937 void *data, u16 len)
2938{
2939 struct mgmt_cp_pin_code_neg_reply *cp = data;
2940
2941 BT_DBG("");
2942
Johan Hedberg1707c602013-03-15 17:07:15 -05002943 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05302944 MGMT_OP_PIN_CODE_NEG_REPLY,
2945 HCI_OP_PIN_CODE_NEG_REPLY, 0);
2946}
2947
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002948static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
2949 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08002950{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002951 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08002952
2953 BT_DBG("");
2954
2955 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002956 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002957 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08002958
Johan Hedberg1707c602013-03-15 17:07:15 -05002959 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002960 MGMT_OP_USER_CONFIRM_REPLY,
2961 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08002962}
2963
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002964static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002965 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08002966{
Johan Hedbergc9c26592011-12-15 00:47:41 +02002967 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08002968
2969 BT_DBG("");
2970
Johan Hedberg1707c602013-03-15 17:07:15 -05002971 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002972 MGMT_OP_USER_CONFIRM_NEG_REPLY,
2973 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08002974}
2975
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
2977 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08002978{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002979 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08002980
2981 BT_DBG("");
2982
Johan Hedberg1707c602013-03-15 17:07:15 -05002983 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002984 MGMT_OP_USER_PASSKEY_REPLY,
2985 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08002986}
2987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002988static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002989 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08002990{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002991 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08002992
2993 BT_DBG("");
2994
Johan Hedberg1707c602013-03-15 17:07:15 -05002995 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002996 MGMT_OP_USER_PASSKEY_NEG_REPLY,
2997 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08002998}
2999
Johan Hedberg13928972013-03-15 17:07:00 -05003000static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003001{
Johan Hedberg13928972013-03-15 17:07:00 -05003002 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003003 struct hci_cp_write_local_name cp;
3004
Johan Hedberg13928972013-03-15 17:07:00 -05003005 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003006
Johan Hedberg890ea892013-03-15 17:06:52 -05003007 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003008}
3009
Johan Hedberg13928972013-03-15 17:07:00 -05003010static void set_name_complete(struct hci_dev *hdev, u8 status)
3011{
3012 struct mgmt_cp_set_local_name *cp;
3013 struct pending_cmd *cmd;
3014
3015 BT_DBG("status 0x%02x", status);
3016
3017 hci_dev_lock(hdev);
3018
3019 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3020 if (!cmd)
3021 goto unlock;
3022
3023 cp = cmd->param;
3024
3025 if (status)
3026 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3027 mgmt_status(status));
3028 else
3029 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3030 cp, sizeof(*cp));
3031
3032 mgmt_pending_remove(cmd);
3033
3034unlock:
3035 hci_dev_unlock(hdev);
3036}
3037
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003038static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003039 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003040{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003041 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003042 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003043 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003044 int err;
3045
3046 BT_DBG("");
3047
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003048 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003049
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003050 /* If the old values are the same as the new ones just return a
3051 * direct command complete event.
3052 */
3053 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3054 !memcmp(hdev->short_name, cp->short_name,
3055 sizeof(hdev->short_name))) {
3056 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3057 data, len);
3058 goto failed;
3059 }
3060
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003061 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003062
Johan Hedbergb5235a62012-02-21 14:32:24 +02003063 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003064 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003065
3066 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003067 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003068 if (err < 0)
3069 goto failed;
3070
3071 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003072 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003073
Johan Hedbergb5235a62012-02-21 14:32:24 +02003074 goto failed;
3075 }
3076
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003077 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003078 if (!cmd) {
3079 err = -ENOMEM;
3080 goto failed;
3081 }
3082
Johan Hedberg13928972013-03-15 17:07:00 -05003083 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3084
Johan Hedberg890ea892013-03-15 17:06:52 -05003085 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003086
3087 if (lmp_bredr_capable(hdev)) {
3088 update_name(&req);
3089 update_eir(&req);
3090 }
3091
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003092 /* The name is stored in the scan response data and so
3093 * no need to udpate the advertising data here.
3094 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003095 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003096 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003097
Johan Hedberg13928972013-03-15 17:07:00 -05003098 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003099 if (err < 0)
3100 mgmt_pending_remove(cmd);
3101
3102failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003103 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003104 return err;
3105}
3106
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003107static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003108 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003109{
Szymon Jancc35938b2011-03-22 13:12:21 +01003110 struct pending_cmd *cmd;
3111 int err;
3112
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003113 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003114
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003115 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003116
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003117 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003118 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003119 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003120 goto unlock;
3121 }
3122
Andre Guedes9a1a1992012-07-24 15:03:48 -03003123 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003124 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003125 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003126 goto unlock;
3127 }
3128
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003129 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003130 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003131 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003132 goto unlock;
3133 }
3134
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003135 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003136 if (!cmd) {
3137 err = -ENOMEM;
3138 goto unlock;
3139 }
3140
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003141 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3142 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3143 0, NULL);
3144 else
3145 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3146
Szymon Jancc35938b2011-03-22 13:12:21 +01003147 if (err < 0)
3148 mgmt_pending_remove(cmd);
3149
3150unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003151 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003152 return err;
3153}
3154
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003155static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003156 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003157{
Szymon Janc2763eda2011-03-22 13:12:22 +01003158 int err;
3159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003160 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003161
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003162 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003163
Marcel Holtmannec109112014-01-10 02:07:30 -08003164 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3165 struct mgmt_cp_add_remote_oob_data *cp = data;
3166 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003167
Marcel Holtmannec109112014-01-10 02:07:30 -08003168 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3169 cp->hash, cp->randomizer);
3170 if (err < 0)
3171 status = MGMT_STATUS_FAILED;
3172 else
3173 status = MGMT_STATUS_SUCCESS;
3174
3175 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3176 status, &cp->addr, sizeof(cp->addr));
3177 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3178 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3179 u8 status;
3180
3181 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3182 cp->hash192,
3183 cp->randomizer192,
3184 cp->hash256,
3185 cp->randomizer256);
3186 if (err < 0)
3187 status = MGMT_STATUS_FAILED;
3188 else
3189 status = MGMT_STATUS_SUCCESS;
3190
3191 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3192 status, &cp->addr, sizeof(cp->addr));
3193 } else {
3194 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3195 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3196 MGMT_STATUS_INVALID_PARAMS);
3197 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003198
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003199 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003200 return err;
3201}
3202
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003203static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003204 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003205{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003206 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003207 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003208 int err;
3209
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003210 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003211
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003212 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003213
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003214 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003215 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003216 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003217 else
Szymon Janca6785be2012-12-13 15:11:21 +01003218 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003219
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003220 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003222
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003223 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003224 return err;
3225}
3226
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003227static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3228{
3229 struct pending_cmd *cmd;
3230 u8 type;
3231 int err;
3232
3233 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3234
3235 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3236 if (!cmd)
3237 return -ENOENT;
3238
3239 type = hdev->discovery.type;
3240
3241 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3242 &type, sizeof(type));
3243 mgmt_pending_remove(cmd);
3244
3245 return err;
3246}
3247
Andre Guedes7c307722013-04-30 15:29:28 -03003248static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3249{
3250 BT_DBG("status %d", status);
3251
3252 if (status) {
3253 hci_dev_lock(hdev);
3254 mgmt_start_discovery_failed(hdev, status);
3255 hci_dev_unlock(hdev);
3256 return;
3257 }
3258
3259 hci_dev_lock(hdev);
3260 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3261 hci_dev_unlock(hdev);
3262
3263 switch (hdev->discovery.type) {
3264 case DISCOV_TYPE_LE:
3265 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003266 DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003267 break;
3268
3269 case DISCOV_TYPE_INTERLEAVED:
3270 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003271 DISCOV_INTERLEAVED_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003272 break;
3273
3274 case DISCOV_TYPE_BREDR:
3275 break;
3276
3277 default:
3278 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3279 }
3280}
3281
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003282static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003283 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003284{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003285 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003286 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003287 struct hci_cp_le_set_scan_param param_cp;
3288 struct hci_cp_le_set_scan_enable enable_cp;
3289 struct hci_cp_inquiry inq_cp;
3290 struct hci_request req;
3291 /* General inquiry access code (GIAC) */
3292 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedberge6fe7982013-10-02 15:45:22 +03003293 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003294 int err;
3295
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003296 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003297
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003298 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003299
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003300 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003301 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003302 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003303 goto failed;
3304 }
3305
Andre Guedes642be6c2012-03-21 00:03:37 -03003306 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3307 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3308 MGMT_STATUS_BUSY);
3309 goto failed;
3310 }
3311
Johan Hedbergff9ef572012-01-04 14:23:45 +02003312 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003313 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003314 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003315 goto failed;
3316 }
3317
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003318 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003319 if (!cmd) {
3320 err = -ENOMEM;
3321 goto failed;
3322 }
3323
Andre Guedes4aab14e2012-02-17 20:39:36 -03003324 hdev->discovery.type = cp->type;
3325
Andre Guedes7c307722013-04-30 15:29:28 -03003326 hci_req_init(&req, hdev);
3327
Andre Guedes4aab14e2012-02-17 20:39:36 -03003328 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003329 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003330 status = mgmt_bredr_support(hdev);
3331 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003332 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003333 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003334 mgmt_pending_remove(cmd);
3335 goto failed;
3336 }
3337
Andre Guedes7c307722013-04-30 15:29:28 -03003338 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3339 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3340 MGMT_STATUS_BUSY);
3341 mgmt_pending_remove(cmd);
3342 goto failed;
3343 }
3344
3345 hci_inquiry_cache_flush(hdev);
3346
3347 memset(&inq_cp, 0, sizeof(inq_cp));
3348 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003349 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003350 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003351 break;
3352
3353 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003354 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003355 status = mgmt_le_support(hdev);
3356 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003357 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003358 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003359 mgmt_pending_remove(cmd);
3360 goto failed;
3361 }
3362
Andre Guedes7c307722013-04-30 15:29:28 -03003363 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003364 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003365 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3366 MGMT_STATUS_NOT_SUPPORTED);
3367 mgmt_pending_remove(cmd);
3368 goto failed;
3369 }
3370
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003371 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003372 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3373 MGMT_STATUS_REJECTED);
3374 mgmt_pending_remove(cmd);
3375 goto failed;
3376 }
3377
3378 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
3379 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3380 MGMT_STATUS_BUSY);
3381 mgmt_pending_remove(cmd);
3382 goto failed;
3383 }
3384
3385 memset(&param_cp, 0, sizeof(param_cp));
3386 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003387 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3388 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Marcel Holtmann79830f62013-10-18 16:38:09 -07003389 param_cp.own_address_type = hdev->own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003390 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3391 &param_cp);
3392
3393 memset(&enable_cp, 0, sizeof(enable_cp));
3394 enable_cp.enable = LE_SCAN_ENABLE;
3395 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3396 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3397 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003398 break;
3399
Andre Guedesf39799f2012-02-17 20:39:35 -03003400 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003401 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3402 MGMT_STATUS_INVALID_PARAMS);
3403 mgmt_pending_remove(cmd);
3404 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003405 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003406
Andre Guedes7c307722013-04-30 15:29:28 -03003407 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003408 if (err < 0)
3409 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003410 else
3411 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003412
3413failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003414 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003415 return err;
3416}
3417
Andre Guedes1183fdc2013-04-30 15:29:35 -03003418static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3419{
3420 struct pending_cmd *cmd;
3421 int err;
3422
3423 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3424 if (!cmd)
3425 return -ENOENT;
3426
3427 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3428 &hdev->discovery.type, sizeof(hdev->discovery.type));
3429 mgmt_pending_remove(cmd);
3430
3431 return err;
3432}
3433
Andre Guedes0e05bba2013-04-30 15:29:33 -03003434static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3435{
3436 BT_DBG("status %d", status);
3437
3438 hci_dev_lock(hdev);
3439
3440 if (status) {
3441 mgmt_stop_discovery_failed(hdev, status);
3442 goto unlock;
3443 }
3444
3445 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3446
3447unlock:
3448 hci_dev_unlock(hdev);
3449}
3450
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003451static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003452 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003453{
Johan Hedbergd9306502012-02-20 23:25:18 +02003454 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003455 struct pending_cmd *cmd;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003456 struct hci_cp_remote_name_req_cancel cp;
3457 struct inquiry_entry *e;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003458 struct hci_request req;
3459 struct hci_cp_le_set_scan_enable enable_cp;
Johan Hedberg14a53662011-04-27 10:29:56 -04003460 int err;
3461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003462 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003463
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003464 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003465
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003466 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003467 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003468 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3469 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003470 goto unlock;
3471 }
3472
3473 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003474 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003475 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3476 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003477 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003478 }
3479
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003480 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003481 if (!cmd) {
3482 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003483 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003484 }
3485
Andre Guedes0e05bba2013-04-30 15:29:33 -03003486 hci_req_init(&req, hdev);
3487
Andre Guedese0d9727e2012-03-20 15:15:36 -03003488 switch (hdev->discovery.state) {
3489 case DISCOVERY_FINDING:
Andre Guedes0e05bba2013-04-30 15:29:33 -03003490 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3491 hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
3492 } else {
3493 cancel_delayed_work(&hdev->le_scan_disable);
3494
3495 memset(&enable_cp, 0, sizeof(enable_cp));
3496 enable_cp.enable = LE_SCAN_DISABLE;
3497 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
3498 sizeof(enable_cp), &enable_cp);
3499 }
Andre Guedesc9ecc482012-03-15 16:52:08 -03003500
Andre Guedese0d9727e2012-03-20 15:15:36 -03003501 break;
3502
3503 case DISCOVERY_RESOLVING:
3504 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003505 NAME_PENDING);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003506 if (!e) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003507 mgmt_pending_remove(cmd);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003508 err = cmd_complete(sk, hdev->id,
3509 MGMT_OP_STOP_DISCOVERY, 0,
3510 &mgmt_cp->type,
3511 sizeof(mgmt_cp->type));
3512 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3513 goto unlock;
3514 }
3515
3516 bacpy(&cp.bdaddr, &e->data.bdaddr);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003517 hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
3518 &cp);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003519
3520 break;
3521
3522 default:
3523 BT_DBG("unknown discovery state %u", hdev->discovery.state);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003524
3525 mgmt_pending_remove(cmd);
3526 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
3527 MGMT_STATUS_FAILED, &mgmt_cp->type,
3528 sizeof(mgmt_cp->type));
3529 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003530 }
3531
Andre Guedes0e05bba2013-04-30 15:29:33 -03003532 err = hci_req_run(&req, stop_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003533 if (err < 0)
3534 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003535 else
3536 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003537
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003538unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003539 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003540 return err;
3541}
3542
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003543static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003544 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003545{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003546 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003547 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003548 int err;
3549
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003550 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003551
Johan Hedberg561aafb2012-01-04 13:31:59 +02003552 hci_dev_lock(hdev);
3553
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003554 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003555 err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003556 MGMT_STATUS_FAILED);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003557 goto failed;
3558 }
3559
Johan Hedberga198e7b2012-02-17 14:27:06 +02003560 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003561 if (!e) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003562 err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003563 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003564 goto failed;
3565 }
3566
3567 if (cp->name_known) {
3568 e->name_state = NAME_KNOWN;
3569 list_del(&e->list);
3570 } else {
3571 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003572 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003573 }
3574
Johan Hedberge3846622013-01-09 15:29:33 +02003575 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3576 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003577
3578failed:
3579 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003580 return err;
3581}
3582
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003583static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003584 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003585{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003586 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003587 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003588 int err;
3589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003590 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003591
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003592 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003593 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3594 MGMT_STATUS_INVALID_PARAMS,
3595 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003596
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003597 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003598
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003599 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003600 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003601 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003602 else
Szymon Janca6785be2012-12-13 15:11:21 +01003603 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003604
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003605 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003606 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003607
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003608 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003609
3610 return err;
3611}
3612
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003613static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003614 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003615{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003616 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003617 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003618 int err;
3619
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003620 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003621
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003622 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003623 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3624 MGMT_STATUS_INVALID_PARAMS,
3625 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003626
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003627 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003628
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003629 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003630 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003631 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003632 else
Szymon Janca6785be2012-12-13 15:11:21 +01003633 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003634
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003635 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003636 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003637
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003638 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003639
3640 return err;
3641}
3642
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003643static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3644 u16 len)
3645{
3646 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003647 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003648 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003649 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003650
3651 BT_DBG("%s", hdev->name);
3652
Szymon Jancc72d4b82012-03-16 16:02:57 +01003653 source = __le16_to_cpu(cp->source);
3654
3655 if (source > 0x0002)
3656 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3657 MGMT_STATUS_INVALID_PARAMS);
3658
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003659 hci_dev_lock(hdev);
3660
Szymon Jancc72d4b82012-03-16 16:02:57 +01003661 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003662 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3663 hdev->devid_product = __le16_to_cpu(cp->product);
3664 hdev->devid_version = __le16_to_cpu(cp->version);
3665
3666 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3667
Johan Hedberg890ea892013-03-15 17:06:52 -05003668 hci_req_init(&req, hdev);
3669 update_eir(&req);
3670 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003671
3672 hci_dev_unlock(hdev);
3673
3674 return err;
3675}
3676
Johan Hedberg4375f102013-09-25 13:26:10 +03003677static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3678{
3679 struct cmd_lookup match = { NULL, hdev };
3680
3681 if (status) {
3682 u8 mgmt_err = mgmt_status(status);
3683
3684 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3685 cmd_status_rsp, &mgmt_err);
3686 return;
3687 }
3688
3689 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3690 &match);
3691
3692 new_settings(hdev, match.sk);
3693
3694 if (match.sk)
3695 sock_put(match.sk);
3696}
3697
Marcel Holtmann21b51872013-10-10 09:47:53 -07003698static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3699 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003700{
3701 struct mgmt_mode *cp = data;
3702 struct pending_cmd *cmd;
3703 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003704 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003705 int err;
3706
3707 BT_DBG("request for %s", hdev->name);
3708
Johan Hedberge6fe7982013-10-02 15:45:22 +03003709 status = mgmt_le_support(hdev);
3710 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003711 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003712 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003713
3714 if (cp->val != 0x00 && cp->val != 0x01)
3715 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3716 MGMT_STATUS_INVALID_PARAMS);
3717
3718 hci_dev_lock(hdev);
3719
3720 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003721 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003722
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003723 /* The following conditions are ones which mean that we should
3724 * not do any HCI communication but directly send a mgmt
3725 * response to user space (after toggling the flag if
3726 * necessary).
3727 */
3728 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003729 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003730 bool changed = false;
3731
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003732 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3733 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003734 changed = true;
3735 }
3736
3737 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3738 if (err < 0)
3739 goto unlock;
3740
3741 if (changed)
3742 err = new_settings(hdev, sk);
3743
3744 goto unlock;
3745 }
3746
3747 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3748 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3749 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3750 MGMT_STATUS_BUSY);
3751 goto unlock;
3752 }
3753
3754 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3755 if (!cmd) {
3756 err = -ENOMEM;
3757 goto unlock;
3758 }
3759
3760 hci_req_init(&req, hdev);
3761
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003762 if (val)
3763 enable_advertising(&req);
3764 else
3765 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003766
3767 err = hci_req_run(&req, set_advertising_complete);
3768 if (err < 0)
3769 mgmt_pending_remove(cmd);
3770
3771unlock:
3772 hci_dev_unlock(hdev);
3773 return err;
3774}
3775
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003776static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3777 void *data, u16 len)
3778{
3779 struct mgmt_cp_set_static_address *cp = data;
3780 int err;
3781
3782 BT_DBG("%s", hdev->name);
3783
Marcel Holtmann62af4442013-10-02 22:10:32 -07003784 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003785 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003786 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003787
3788 if (hdev_is_powered(hdev))
3789 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3790 MGMT_STATUS_REJECTED);
3791
3792 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3793 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3794 return cmd_status(sk, hdev->id,
3795 MGMT_OP_SET_STATIC_ADDRESS,
3796 MGMT_STATUS_INVALID_PARAMS);
3797
3798 /* Two most significant bits shall be set */
3799 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3800 return cmd_status(sk, hdev->id,
3801 MGMT_OP_SET_STATIC_ADDRESS,
3802 MGMT_STATUS_INVALID_PARAMS);
3803 }
3804
3805 hci_dev_lock(hdev);
3806
3807 bacpy(&hdev->static_addr, &cp->bdaddr);
3808
3809 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3810
3811 hci_dev_unlock(hdev);
3812
3813 return err;
3814}
3815
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003816static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3817 void *data, u16 len)
3818{
3819 struct mgmt_cp_set_scan_params *cp = data;
3820 __u16 interval, window;
3821 int err;
3822
3823 BT_DBG("%s", hdev->name);
3824
3825 if (!lmp_le_capable(hdev))
3826 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3827 MGMT_STATUS_NOT_SUPPORTED);
3828
3829 interval = __le16_to_cpu(cp->interval);
3830
3831 if (interval < 0x0004 || interval > 0x4000)
3832 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3833 MGMT_STATUS_INVALID_PARAMS);
3834
3835 window = __le16_to_cpu(cp->window);
3836
3837 if (window < 0x0004 || window > 0x4000)
3838 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3839 MGMT_STATUS_INVALID_PARAMS);
3840
Marcel Holtmann899e1072013-10-14 09:55:32 -07003841 if (window > interval)
3842 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3843 MGMT_STATUS_INVALID_PARAMS);
3844
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003845 hci_dev_lock(hdev);
3846
3847 hdev->le_scan_interval = interval;
3848 hdev->le_scan_window = window;
3849
3850 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3851
3852 hci_dev_unlock(hdev);
3853
3854 return err;
3855}
3856
Johan Hedberg33e38b32013-03-15 17:07:05 -05003857static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3858{
3859 struct pending_cmd *cmd;
3860
3861 BT_DBG("status 0x%02x", status);
3862
3863 hci_dev_lock(hdev);
3864
3865 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3866 if (!cmd)
3867 goto unlock;
3868
3869 if (status) {
3870 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3871 mgmt_status(status));
3872 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05003873 struct mgmt_mode *cp = cmd->param;
3874
3875 if (cp->val)
3876 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
3877 else
3878 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
3879
Johan Hedberg33e38b32013-03-15 17:07:05 -05003880 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3881 new_settings(hdev, cmd->sk);
3882 }
3883
3884 mgmt_pending_remove(cmd);
3885
3886unlock:
3887 hci_dev_unlock(hdev);
3888}
3889
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003890static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003891 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03003892{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003893 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05003894 struct pending_cmd *cmd;
3895 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03003896 int err;
3897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003898 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003899
Johan Hedberg56f87902013-10-02 13:43:13 +03003900 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
3901 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03003902 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3903 MGMT_STATUS_NOT_SUPPORTED);
3904
Johan Hedberga7e80f22013-01-09 16:05:19 +02003905 if (cp->val != 0x00 && cp->val != 0x01)
3906 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3907 MGMT_STATUS_INVALID_PARAMS);
3908
Johan Hedberg5400c042012-02-21 16:40:33 +02003909 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003910 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003911 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02003912
3913 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003914 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003915 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003916
3917 hci_dev_lock(hdev);
3918
Johan Hedberg05cbf292013-03-15 17:07:07 -05003919 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
3920 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3921 MGMT_STATUS_BUSY);
3922 goto unlock;
3923 }
3924
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05003925 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
3926 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
3927 hdev);
3928 goto unlock;
3929 }
3930
Johan Hedberg33e38b32013-03-15 17:07:05 -05003931 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
3932 data, len);
3933 if (!cmd) {
3934 err = -ENOMEM;
3935 goto unlock;
3936 }
3937
3938 hci_req_init(&req, hdev);
3939
Johan Hedberg406d7802013-03-15 17:07:09 -05003940 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05003941
3942 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003943 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003944 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003945 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05003946 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003947 }
3948
Johan Hedberg33e38b32013-03-15 17:07:05 -05003949unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03003950 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05003951
Antti Julkuf6422ec2011-06-22 13:11:56 +03003952 return err;
3953}
3954
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03003955static void set_bredr_scan(struct hci_request *req)
3956{
3957 struct hci_dev *hdev = req->hdev;
3958 u8 scan = 0;
3959
3960 /* Ensure that fast connectable is disabled. This function will
3961 * not do anything if the page scan parameters are already what
3962 * they should be.
3963 */
3964 write_fast_connectable(req, false);
3965
3966 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
3967 scan |= SCAN_PAGE;
3968 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
3969 scan |= SCAN_INQUIRY;
3970
3971 if (scan)
3972 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
3973}
3974
Johan Hedberg0663ca22013-10-02 13:43:14 +03003975static void set_bredr_complete(struct hci_dev *hdev, u8 status)
3976{
3977 struct pending_cmd *cmd;
3978
3979 BT_DBG("status 0x%02x", status);
3980
3981 hci_dev_lock(hdev);
3982
3983 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
3984 if (!cmd)
3985 goto unlock;
3986
3987 if (status) {
3988 u8 mgmt_err = mgmt_status(status);
3989
3990 /* We need to restore the flag if related HCI commands
3991 * failed.
3992 */
3993 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
3994
3995 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
3996 } else {
3997 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
3998 new_settings(hdev, cmd->sk);
3999 }
4000
4001 mgmt_pending_remove(cmd);
4002
4003unlock:
4004 hci_dev_unlock(hdev);
4005}
4006
4007static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4008{
4009 struct mgmt_mode *cp = data;
4010 struct pending_cmd *cmd;
4011 struct hci_request req;
4012 int err;
4013
4014 BT_DBG("request for %s", hdev->name);
4015
4016 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4017 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4018 MGMT_STATUS_NOT_SUPPORTED);
4019
4020 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4021 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4022 MGMT_STATUS_REJECTED);
4023
4024 if (cp->val != 0x00 && cp->val != 0x01)
4025 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4026 MGMT_STATUS_INVALID_PARAMS);
4027
4028 hci_dev_lock(hdev);
4029
4030 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4031 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4032 goto unlock;
4033 }
4034
4035 if (!hdev_is_powered(hdev)) {
4036 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004037 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4038 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4039 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4040 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4041 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4042 }
4043
4044 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4045
4046 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4047 if (err < 0)
4048 goto unlock;
4049
4050 err = new_settings(hdev, sk);
4051 goto unlock;
4052 }
4053
4054 /* Reject disabling when powered on */
4055 if (!cp->val) {
4056 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4057 MGMT_STATUS_REJECTED);
4058 goto unlock;
4059 }
4060
4061 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4062 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4063 MGMT_STATUS_BUSY);
4064 goto unlock;
4065 }
4066
4067 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4068 if (!cmd) {
4069 err = -ENOMEM;
4070 goto unlock;
4071 }
4072
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004073 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004074 * generates the correct flags.
4075 */
4076 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4077
4078 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004079
4080 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4081 set_bredr_scan(&req);
4082
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004083 /* Since only the advertising data flags will change, there
4084 * is no need to update the scan response data.
4085 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004086 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004087
Johan Hedberg0663ca22013-10-02 13:43:14 +03004088 err = hci_req_run(&req, set_bredr_complete);
4089 if (err < 0)
4090 mgmt_pending_remove(cmd);
4091
4092unlock:
4093 hci_dev_unlock(hdev);
4094 return err;
4095}
4096
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004097static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4098 void *data, u16 len)
4099{
4100 struct mgmt_mode *cp = data;
4101 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004102 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004103 int err;
4104
4105 BT_DBG("request for %s", hdev->name);
4106
4107 status = mgmt_bredr_support(hdev);
4108 if (status)
4109 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4110 status);
4111
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004112 if (!lmp_sc_capable(hdev) &&
4113 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004114 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4115 MGMT_STATUS_NOT_SUPPORTED);
4116
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004117 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004118 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4119 MGMT_STATUS_INVALID_PARAMS);
4120
4121 hci_dev_lock(hdev);
4122
4123 if (!hdev_is_powered(hdev)) {
4124 bool changed;
4125
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004126 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004127 changed = !test_and_set_bit(HCI_SC_ENABLED,
4128 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004129 if (cp->val == 0x02)
4130 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4131 else
4132 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4133 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004134 changed = test_and_clear_bit(HCI_SC_ENABLED,
4135 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004136 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4137 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004138
4139 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4140 if (err < 0)
4141 goto failed;
4142
4143 if (changed)
4144 err = new_settings(hdev, sk);
4145
4146 goto failed;
4147 }
4148
4149 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4150 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4151 MGMT_STATUS_BUSY);
4152 goto failed;
4153 }
4154
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004155 val = !!cp->val;
4156
4157 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4158 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004159 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4160 goto failed;
4161 }
4162
4163 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4164 if (!cmd) {
4165 err = -ENOMEM;
4166 goto failed;
4167 }
4168
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004169 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004170 if (err < 0) {
4171 mgmt_pending_remove(cmd);
4172 goto failed;
4173 }
4174
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004175 if (cp->val == 0x02)
4176 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4177 else
4178 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4179
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004180failed:
4181 hci_dev_unlock(hdev);
4182 return err;
4183}
4184
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004185static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4186 void *data, u16 len)
4187{
4188 struct mgmt_mode *cp = data;
4189 bool changed;
4190 int err;
4191
4192 BT_DBG("request for %s", hdev->name);
4193
4194 if (cp->val != 0x00 && cp->val != 0x01)
4195 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4196 MGMT_STATUS_INVALID_PARAMS);
4197
4198 hci_dev_lock(hdev);
4199
4200 if (cp->val)
4201 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4202 else
4203 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4204
4205 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4206 if (err < 0)
4207 goto unlock;
4208
4209 if (changed)
4210 err = new_settings(hdev, sk);
4211
4212unlock:
4213 hci_dev_unlock(hdev);
4214 return err;
4215}
4216
Johan Hedberg41edf162014-02-18 10:19:35 +02004217static bool irk_is_valid(struct mgmt_irk_info *irk)
4218{
4219 switch (irk->addr.type) {
4220 case BDADDR_LE_PUBLIC:
4221 return true;
4222
4223 case BDADDR_LE_RANDOM:
4224 /* Two most significant bits shall be set */
4225 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4226 return false;
4227 return true;
4228 }
4229
4230 return false;
4231}
4232
4233static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4234 u16 len)
4235{
4236 struct mgmt_cp_load_irks *cp = cp_data;
4237 u16 irk_count, expected_len;
4238 int i, err;
4239
4240 BT_DBG("request for %s", hdev->name);
4241
4242 if (!lmp_le_capable(hdev))
4243 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4244 MGMT_STATUS_NOT_SUPPORTED);
4245
4246 irk_count = __le16_to_cpu(cp->irk_count);
4247
4248 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4249 if (expected_len != len) {
4250 BT_ERR("load_irks: expected %u bytes, got %u bytes",
4251 len, expected_len);
4252 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4253 MGMT_STATUS_INVALID_PARAMS);
4254 }
4255
4256 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4257
4258 for (i = 0; i < irk_count; i++) {
4259 struct mgmt_irk_info *key = &cp->irks[i];
4260
4261 if (!irk_is_valid(key))
4262 return cmd_status(sk, hdev->id,
4263 MGMT_OP_LOAD_IRKS,
4264 MGMT_STATUS_INVALID_PARAMS);
4265 }
4266
4267 hci_dev_lock(hdev);
4268
4269 hci_smp_irks_clear(hdev);
4270
4271 for (i = 0; i < irk_count; i++) {
4272 struct mgmt_irk_info *irk = &cp->irks[i];
4273 u8 addr_type;
4274
4275 if (irk->addr.type == BDADDR_LE_PUBLIC)
4276 addr_type = ADDR_LE_DEV_PUBLIC;
4277 else
4278 addr_type = ADDR_LE_DEV_RANDOM;
4279
4280 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4281 BDADDR_ANY);
4282 }
4283
4284 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4285
4286 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4287
4288 hci_dev_unlock(hdev);
4289
4290 return err;
4291}
4292
Johan Hedberg3f706b72013-01-20 14:27:16 +02004293static bool ltk_is_valid(struct mgmt_ltk_info *key)
4294{
4295 if (key->master != 0x00 && key->master != 0x01)
4296 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004297
4298 switch (key->addr.type) {
4299 case BDADDR_LE_PUBLIC:
4300 return true;
4301
4302 case BDADDR_LE_RANDOM:
4303 /* Two most significant bits shall be set */
4304 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4305 return false;
4306 return true;
4307 }
4308
4309 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004310}
4311
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004312static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004313 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004314{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004315 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4316 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004317 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004318
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004319 BT_DBG("request for %s", hdev->name);
4320
4321 if (!lmp_le_capable(hdev))
4322 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4323 MGMT_STATUS_NOT_SUPPORTED);
4324
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004325 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004326
4327 expected_len = sizeof(*cp) + key_count *
4328 sizeof(struct mgmt_ltk_info);
4329 if (expected_len != len) {
4330 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004331 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004332 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004333 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004334 }
4335
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004336 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004337
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004338 for (i = 0; i < key_count; i++) {
4339 struct mgmt_ltk_info *key = &cp->keys[i];
4340
Johan Hedberg3f706b72013-01-20 14:27:16 +02004341 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004342 return cmd_status(sk, hdev->id,
4343 MGMT_OP_LOAD_LONG_TERM_KEYS,
4344 MGMT_STATUS_INVALID_PARAMS);
4345 }
4346
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004347 hci_dev_lock(hdev);
4348
4349 hci_smp_ltks_clear(hdev);
4350
4351 for (i = 0; i < key_count; i++) {
4352 struct mgmt_ltk_info *key = &cp->keys[i];
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004353 u8 type, addr_type;
4354
4355 if (key->addr.type == BDADDR_LE_PUBLIC)
4356 addr_type = ADDR_LE_DEV_PUBLIC;
4357 else
4358 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004359
4360 if (key->master)
4361 type = HCI_SMP_LTK;
4362 else
4363 type = HCI_SMP_LTK_SLAVE;
4364
Johan Hedberg35d70272014-02-19 14:57:47 +02004365 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
4366 key->type, key->val, key->enc_size, key->ediv,
4367 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004368 }
4369
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004370 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4371 NULL, 0);
4372
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004373 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004374
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004375 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004376}
4377
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004378static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004379 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4380 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004381 bool var_len;
4382 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004383} mgmt_handlers[] = {
4384 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004385 { read_version, false, MGMT_READ_VERSION_SIZE },
4386 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4387 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4388 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4389 { set_powered, false, MGMT_SETTING_SIZE },
4390 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4391 { set_connectable, false, MGMT_SETTING_SIZE },
4392 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4393 { set_pairable, false, MGMT_SETTING_SIZE },
4394 { set_link_security, false, MGMT_SETTING_SIZE },
4395 { set_ssp, false, MGMT_SETTING_SIZE },
4396 { set_hs, false, MGMT_SETTING_SIZE },
4397 { set_le, false, MGMT_SETTING_SIZE },
4398 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4399 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4400 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4401 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4402 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4403 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4404 { disconnect, false, MGMT_DISCONNECT_SIZE },
4405 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4406 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4407 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4408 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4409 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4410 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4411 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4412 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4413 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4414 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4415 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4416 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004417 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004418 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4419 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4420 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4421 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4422 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4423 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004424 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004425 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004426 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004427 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004428 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004429 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004430 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004431 { },
4432 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004433};
4434
4435
Johan Hedberg03811012010-12-08 00:21:06 +02004436int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4437{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004438 void *buf;
4439 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004440 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004441 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004442 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004443 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004444 int err;
4445
4446 BT_DBG("got %zu bytes", msglen);
4447
4448 if (msglen < sizeof(*hdr))
4449 return -EINVAL;
4450
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004451 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004452 if (!buf)
4453 return -ENOMEM;
4454
4455 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4456 err = -EFAULT;
4457 goto done;
4458 }
4459
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004460 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004461 opcode = __le16_to_cpu(hdr->opcode);
4462 index = __le16_to_cpu(hdr->index);
4463 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004464
4465 if (len != msglen - sizeof(*hdr)) {
4466 err = -EINVAL;
4467 goto done;
4468 }
4469
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004470 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004471 hdev = hci_dev_get(index);
4472 if (!hdev) {
4473 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004474 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004475 goto done;
4476 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004477
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004478 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4479 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004480 err = cmd_status(sk, index, opcode,
4481 MGMT_STATUS_INVALID_INDEX);
4482 goto done;
4483 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004484 }
4485
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004486 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004487 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004488 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004489 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004490 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004491 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004492 }
4493
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004494 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004495 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004496 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004497 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004498 goto done;
4499 }
4500
Johan Hedbergbe22b542012-03-01 22:24:41 +02004501 handler = &mgmt_handlers[opcode];
4502
4503 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004504 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004505 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004506 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004507 goto done;
4508 }
4509
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004510 if (hdev)
4511 mgmt_init_hdev(sk, hdev);
4512
4513 cp = buf + sizeof(*hdr);
4514
Johan Hedbergbe22b542012-03-01 22:24:41 +02004515 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004516 if (err < 0)
4517 goto done;
4518
Johan Hedberg03811012010-12-08 00:21:06 +02004519 err = msglen;
4520
4521done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004522 if (hdev)
4523 hci_dev_put(hdev);
4524
Johan Hedberg03811012010-12-08 00:21:06 +02004525 kfree(buf);
4526 return err;
4527}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004528
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004529void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004530{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004531 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004532 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004533
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004534 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004535}
4536
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004537void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004538{
Johan Hedberg5f159032012-03-02 03:13:19 +02004539 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004540
Marcel Holtmann1514b892013-10-06 08:25:01 -07004541 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004542 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004543
Johan Hedberg744cf192011-11-08 20:40:14 +02004544 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004545
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004546 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004547}
4548
Johan Hedberg229ab392013-03-15 17:06:53 -05004549static void powered_complete(struct hci_dev *hdev, u8 status)
4550{
4551 struct cmd_lookup match = { NULL, hdev };
4552
4553 BT_DBG("status 0x%02x", status);
4554
4555 hci_dev_lock(hdev);
4556
4557 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4558
4559 new_settings(hdev, match.sk);
4560
4561 hci_dev_unlock(hdev);
4562
4563 if (match.sk)
4564 sock_put(match.sk);
4565}
4566
Johan Hedberg70da6242013-03-15 17:06:51 -05004567static int powered_update_hci(struct hci_dev *hdev)
4568{
Johan Hedberg890ea892013-03-15 17:06:52 -05004569 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004570 u8 link_sec;
4571
Johan Hedberg890ea892013-03-15 17:06:52 -05004572 hci_req_init(&req, hdev);
4573
Johan Hedberg70da6242013-03-15 17:06:51 -05004574 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4575 !lmp_host_ssp_capable(hdev)) {
4576 u8 ssp = 1;
4577
Johan Hedberg890ea892013-03-15 17:06:52 -05004578 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004579 }
4580
Johan Hedbergc73eee92013-04-19 18:35:21 +03004581 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4582 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05004583 struct hci_cp_write_le_host_supported cp;
4584
4585 cp.le = 1;
4586 cp.simul = lmp_le_br_capable(hdev);
4587
4588 /* Check first if we already have the right
4589 * host state (host features set)
4590 */
4591 if (cp.le != lmp_host_le_capable(hdev) ||
4592 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05004593 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
4594 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004595 }
4596
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004597 if (lmp_le_capable(hdev)) {
4598 /* Set random address to static address if configured */
4599 if (bacmp(&hdev->static_addr, BDADDR_ANY))
4600 hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6,
4601 &hdev->static_addr);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004602
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004603 /* Make sure the controller has a good default for
4604 * advertising data. This also applies to the case
4605 * where BR/EDR was toggled during the AUTO_OFF phase.
4606 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004607 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004608 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004609 update_scan_rsp_data(&req);
4610 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004611
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004612 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
4613 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03004614 }
4615
Johan Hedberg70da6242013-03-15 17:06:51 -05004616 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4617 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05004618 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
4619 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05004620
4621 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03004622 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
4623 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004624 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05004625 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004626 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05004627 }
4628
Johan Hedberg229ab392013-03-15 17:06:53 -05004629 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05004630}
4631
Johan Hedberg744cf192011-11-08 20:40:14 +02004632int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02004633{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02004634 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05004635 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
4636 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004637 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004638
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004639 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
4640 return 0;
4641
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004642 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05004643 if (powered_update_hci(hdev) == 0)
4644 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02004645
Johan Hedberg229ab392013-03-15 17:06:53 -05004646 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
4647 &match);
4648 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004649 }
4650
Johan Hedberg229ab392013-03-15 17:06:53 -05004651 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4652 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
4653
4654 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
4655 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
4656 zero_cod, sizeof(zero_cod), NULL);
4657
4658new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004659 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004660
4661 if (match.sk)
4662 sock_put(match.sk);
4663
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004664 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004665}
Johan Hedberg73f22f62010-12-29 16:00:25 +02004666
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004667void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03004668{
4669 struct pending_cmd *cmd;
4670 u8 status;
4671
4672 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
4673 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004674 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03004675
4676 if (err == -ERFKILL)
4677 status = MGMT_STATUS_RFKILLED;
4678 else
4679 status = MGMT_STATUS_FAILED;
4680
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004681 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004682
4683 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004684}
4685
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004686void mgmt_discoverable_timeout(struct hci_dev *hdev)
4687{
4688 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004689
4690 hci_dev_lock(hdev);
4691
4692 /* When discoverable timeout triggers, then just make sure
4693 * the limited discoverable flag is cleared. Even in the case
4694 * of a timeout triggered from general discoverable, it is
4695 * safe to unconditionally clear the flag.
4696 */
4697 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004698 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004699
4700 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03004701 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4702 u8 scan = SCAN_PAGE;
4703 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
4704 sizeof(scan), &scan);
4705 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004706 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004707 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004708 hci_req_run(&req, NULL);
4709
4710 hdev->discov_timeout = 0;
4711
Johan Hedberg9a43e252013-10-20 19:00:07 +03004712 new_settings(hdev, NULL);
4713
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004714 hci_dev_unlock(hdev);
4715}
4716
Marcel Holtmann86a75642013-10-15 06:33:54 -07004717void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02004718{
Marcel Holtmann86a75642013-10-15 06:33:54 -07004719 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02004720
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004721 /* Nothing needed here if there's a pending command since that
4722 * commands request completion callback takes care of everything
4723 * necessary.
4724 */
4725 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07004726 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004727
Johan Hedberg9a43e252013-10-20 19:00:07 +03004728 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07004729 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004730 } else {
4731 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07004732 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004733 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004734
Johan Hedberg9a43e252013-10-20 19:00:07 +03004735 if (changed) {
4736 struct hci_request req;
4737
4738 /* In case this change in discoverable was triggered by
4739 * a disabling of connectable there could be a need to
4740 * update the advertising flags.
4741 */
4742 hci_req_init(&req, hdev);
4743 update_adv_data(&req);
4744 hci_req_run(&req, NULL);
4745
Marcel Holtmann86a75642013-10-15 06:33:54 -07004746 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004747 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004748}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004749
Marcel Holtmanna3309162013-10-15 06:33:55 -07004750void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004751{
Marcel Holtmanna3309162013-10-15 06:33:55 -07004752 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004753
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004754 /* Nothing needed here if there's a pending command since that
4755 * commands request completion callback takes care of everything
4756 * necessary.
4757 */
4758 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07004759 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004760
Marcel Holtmanna3309162013-10-15 06:33:55 -07004761 if (connectable)
4762 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
4763 else
4764 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004765
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004766 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07004767 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004768}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02004769
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07004770void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004771{
Johan Hedbergca69b792011-11-11 18:10:00 +02004772 u8 mgmt_err = mgmt_status(status);
4773
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004774 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02004775 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004776 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004777
4778 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02004779 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004780 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004781}
4782
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004783void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
4784 bool persistent)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02004785{
Johan Hedberg86742e12011-11-07 23:13:38 +02004786 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02004787
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004788 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02004789
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004790 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02004791 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03004792 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004793 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03004794 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004795 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02004796
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004797 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02004798}
Johan Hedbergf7520542011-01-20 12:34:39 +02004799
Johan Hedbergba74b662014-02-19 14:57:45 +02004800void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004801{
4802 struct mgmt_ev_new_long_term_key ev;
4803
4804 memset(&ev, 0, sizeof(ev));
4805
Marcel Holtmann5192d302014-02-19 17:11:58 -08004806 /* Devices using resolvable or non-resolvable random addresses
4807 * without providing an indentity resolving key don't require
4808 * to store long term keys. Their addresses will change the
4809 * next time around.
4810 *
4811 * Only when a remote device provides an identity address
4812 * make sure the long term key is stored. If the remote
4813 * identity is known, the long term keys are internally
4814 * mapped to the identity address. So allow static random
4815 * and public addresses here.
4816 */
Johan Hedbergba74b662014-02-19 14:57:45 +02004817 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
4818 (key->bdaddr.b[5] & 0xc0) != 0xc0)
4819 ev.store_hint = 0x00;
4820 else
4821 ev.store_hint = 0x01;
4822
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004823 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03004824 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Marcel Holtmannd40f3ee2014-01-31 18:42:17 -08004825 ev.key.type = key->authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004826 ev.key.enc_size = key->enc_size;
4827 ev.key.ediv = key->ediv;
4828
4829 if (key->type == HCI_SMP_LTK)
4830 ev.key.master = 1;
4831
4832 memcpy(ev.key.rand, key->rand, sizeof(key->rand));
4833 memcpy(ev.key.val, key->val, sizeof(key->val));
4834
Marcel Holtmann083368f2013-10-15 14:26:29 -07004835 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004836}
4837
Johan Hedberg95fbac82014-02-19 15:18:31 +02004838void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
4839{
4840 struct mgmt_ev_new_irk ev;
4841
4842 memset(&ev, 0, sizeof(ev));
4843
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08004844 /* For identity resolving keys from devices that are already
4845 * using a public address or static random address, do not
4846 * ask for storing this key. The identity resolving key really
4847 * is only mandatory for devices using resovlable random
4848 * addresses.
4849 *
4850 * Storing all identity resolving keys has the downside that
4851 * they will be also loaded on next boot of they system. More
4852 * identity resolving keys, means more time during scanning is
4853 * needed to actually resolve these addresses.
4854 */
4855 if (bacmp(&irk->rpa, BDADDR_ANY))
4856 ev.store_hint = 0x01;
4857 else
4858 ev.store_hint = 0x00;
4859
Johan Hedberg95fbac82014-02-19 15:18:31 +02004860 bacpy(&ev.rpa, &irk->rpa);
4861 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
4862 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
4863 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
4864
4865 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
4866}
4867
Marcel Holtmann94933992013-10-15 10:26:39 -07004868static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
4869 u8 data_len)
4870{
4871 eir[eir_len++] = sizeof(type) + data_len;
4872 eir[eir_len++] = type;
4873 memcpy(&eir[eir_len], data, data_len);
4874 eir_len += data_len;
4875
4876 return eir_len;
4877}
4878
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07004879void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
4880 u8 addr_type, u32 flags, u8 *name, u8 name_len,
4881 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02004882{
Johan Hedbergb644ba32012-01-17 21:48:47 +02004883 char buf[512];
4884 struct mgmt_ev_device_connected *ev = (void *) buf;
4885 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02004886
Johan Hedbergb644ba32012-01-17 21:48:47 +02004887 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03004888 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02004889
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02004890 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02004891
Johan Hedbergb644ba32012-01-17 21:48:47 +02004892 if (name_len > 0)
4893 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004894 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02004895
4896 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08004897 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004898 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02004899
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02004900 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02004901
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07004902 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
4903 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02004904}
4905
Johan Hedberg8962ee72011-01-20 12:40:27 +02004906static void disconnect_rsp(struct pending_cmd *cmd, void *data)
4907{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01004908 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004909 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02004910 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004911
Johan Hedberg88c3df12012-02-09 14:27:38 +02004912 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4913 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004914
Johan Hedbergaee9b2182012-02-18 15:07:59 +02004915 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004916 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02004917
4918 *sk = cmd->sk;
4919 sock_hold(*sk);
4920
Johan Hedberga664b5b2011-02-19 12:06:02 -03004921 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02004922}
4923
Johan Hedberg124f6e32012-02-09 13:50:12 +02004924static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02004925{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02004926 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02004927 struct mgmt_cp_unpair_device *cp = cmd->param;
4928 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02004929
4930 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02004931 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4932 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02004933
Johan Hedbergb1078ad2012-02-09 17:21:16 +02004934 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
4935
Johan Hedbergaee9b2182012-02-18 15:07:59 +02004936 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02004937
4938 mgmt_pending_remove(cmd);
4939}
4940
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07004941void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
4942 u8 link_type, u8 addr_type, u8 reason)
Johan Hedbergf7520542011-01-20 12:34:39 +02004943{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02004944 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004945 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004946
Andre Guedes57eb7762013-10-30 19:01:41 -03004947 if (link_type != ACL_LINK && link_type != LE_LINK)
4948 return;
4949
Johan Hedberg744cf192011-11-08 20:40:14 +02004950 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02004951
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02004952 bacpy(&ev.addr.bdaddr, bdaddr);
4953 ev.addr.type = link_to_bdaddr(link_type, addr_type);
4954 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02004955
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07004956 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02004957
4958 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01004959 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02004960
Johan Hedberg124f6e32012-02-09 13:50:12 +02004961 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004962 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02004963}
4964
Marcel Holtmann78929242013-10-06 23:55:47 -07004965void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
4966 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02004967{
Andre Guedes3655bba2013-10-30 19:01:40 -03004968 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
4969 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02004970 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004971 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004972
Jefferson Delfes36a75f12012-09-18 13:36:54 -04004973 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
4974 hdev);
4975
Johan Hedberg2e58ef32011-11-08 20:40:15 +02004976 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02004977 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07004978 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004979
Andre Guedes3655bba2013-10-30 19:01:40 -03004980 cp = cmd->param;
4981
4982 if (bacmp(bdaddr, &cp->addr.bdaddr))
4983 return;
4984
4985 if (cp->addr.type != bdaddr_type)
4986 return;
4987
Johan Hedberg88c3df12012-02-09 14:27:38 +02004988 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03004989 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02004990
Marcel Holtmann78929242013-10-06 23:55:47 -07004991 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
4992 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02004993
Johan Hedberga664b5b2011-02-19 12:06:02 -03004994 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02004995}
Johan Hedberg17d5c042011-01-22 06:09:08 +02004996
Marcel Holtmann445608d2013-10-06 23:55:48 -07004997void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
4998 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02004999{
5000 struct mgmt_ev_connect_failed ev;
5001
Johan Hedberg4c659c32011-11-07 23:13:39 +02005002 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005003 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005004 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005005
Marcel Holtmann445608d2013-10-06 23:55:48 -07005006 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005007}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005008
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005009void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005010{
5011 struct mgmt_ev_pin_code_request ev;
5012
Johan Hedbergd8457692012-02-17 14:24:57 +02005013 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005014 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005015 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005016
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005017 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005018}
5019
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005020void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5021 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005022{
5023 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005024 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005025
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005026 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005027 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005028 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005029
Johan Hedbergd8457692012-02-17 14:24:57 +02005030 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005031 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005032
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005033 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5034 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005035
Johan Hedberga664b5b2011-02-19 12:06:02 -03005036 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005037}
5038
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005039void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5040 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005041{
5042 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005043 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005044
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005045 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005046 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005047 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005048
Johan Hedbergd8457692012-02-17 14:24:57 +02005049 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005050 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005051
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005052 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5053 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005054
Johan Hedberga664b5b2011-02-19 12:06:02 -03005055 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005056}
Johan Hedberga5c29682011-02-19 12:05:57 -03005057
Johan Hedberg744cf192011-11-08 20:40:14 +02005058int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005059 u8 link_type, u8 addr_type, __le32 value,
5060 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005061{
5062 struct mgmt_ev_user_confirm_request ev;
5063
Johan Hedberg744cf192011-11-08 20:40:14 +02005064 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005065
Johan Hedberg272d90d2012-02-09 15:26:12 +02005066 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005067 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005068 ev.confirm_hint = confirm_hint;
Andrei Emeltchenko78e8098e2012-03-09 13:00:50 +02005069 ev.value = value;
Johan Hedberga5c29682011-02-19 12:05:57 -03005070
Johan Hedberg744cf192011-11-08 20:40:14 +02005071 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005072 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005073}
5074
Johan Hedberg272d90d2012-02-09 15:26:12 +02005075int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005076 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005077{
5078 struct mgmt_ev_user_passkey_request ev;
5079
5080 BT_DBG("%s", hdev->name);
5081
Johan Hedberg272d90d2012-02-09 15:26:12 +02005082 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005083 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005084
5085 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005086 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005087}
5088
Brian Gix0df4c182011-11-16 13:53:13 -08005089static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005090 u8 link_type, u8 addr_type, u8 status,
5091 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005092{
5093 struct pending_cmd *cmd;
5094 struct mgmt_rp_user_confirm_reply rp;
5095 int err;
5096
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005097 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005098 if (!cmd)
5099 return -ENOENT;
5100
Johan Hedberg272d90d2012-02-09 15:26:12 +02005101 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005102 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005103 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005104 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005105
Johan Hedberga664b5b2011-02-19 12:06:02 -03005106 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005107
5108 return err;
5109}
5110
Johan Hedberg744cf192011-11-08 20:40:14 +02005111int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005112 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005113{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005114 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005115 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005116}
5117
Johan Hedberg272d90d2012-02-09 15:26:12 +02005118int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005119 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005120{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005121 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005122 status,
5123 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005124}
Johan Hedberg2a611692011-02-19 12:06:00 -03005125
Brian Gix604086b2011-11-23 08:28:33 -08005126int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005127 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005128{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005129 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005130 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005131}
5132
Johan Hedberg272d90d2012-02-09 15:26:12 +02005133int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005134 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005135{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005136 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005137 status,
5138 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005139}
5140
Johan Hedberg92a25252012-09-06 18:39:26 +03005141int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5142 u8 link_type, u8 addr_type, u32 passkey,
5143 u8 entered)
5144{
5145 struct mgmt_ev_passkey_notify ev;
5146
5147 BT_DBG("%s", hdev->name);
5148
5149 bacpy(&ev.addr.bdaddr, bdaddr);
5150 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5151 ev.passkey = __cpu_to_le32(passkey);
5152 ev.entered = entered;
5153
5154 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5155}
5156
Marcel Holtmanne5460992013-10-15 14:26:23 -07005157void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5158 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005159{
5160 struct mgmt_ev_auth_failed ev;
5161
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005162 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005163 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005164 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005165
Marcel Holtmanne5460992013-10-15 14:26:23 -07005166 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005167}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005168
Marcel Holtmann464996a2013-10-15 14:26:24 -07005169void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005170{
5171 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005172 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005173
5174 if (status) {
5175 u8 mgmt_err = mgmt_status(status);
5176 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005177 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005178 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005179 }
5180
Marcel Holtmann464996a2013-10-15 14:26:24 -07005181 if (test_bit(HCI_AUTH, &hdev->flags))
5182 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5183 &hdev->dev_flags);
5184 else
5185 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5186 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005187
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005188 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005189 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005190
Johan Hedberg47990ea2012-02-22 11:58:37 +02005191 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005192 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005193
5194 if (match.sk)
5195 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005196}
5197
Johan Hedberg890ea892013-03-15 17:06:52 -05005198static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005199{
Johan Hedberg890ea892013-03-15 17:06:52 -05005200 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005201 struct hci_cp_write_eir cp;
5202
Johan Hedberg976eb202012-10-24 21:12:01 +03005203 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005204 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005205
Johan Hedbergc80da272012-02-22 15:38:48 +02005206 memset(hdev->eir, 0, sizeof(hdev->eir));
5207
Johan Hedbergcacaf522012-02-21 00:52:42 +02005208 memset(&cp, 0, sizeof(cp));
5209
Johan Hedberg890ea892013-03-15 17:06:52 -05005210 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005211}
5212
Marcel Holtmann3e248562013-10-15 14:26:25 -07005213void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005214{
5215 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005216 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005217 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005218
5219 if (status) {
5220 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005221
5222 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005223 &hdev->dev_flags)) {
5224 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005225 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005226 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005227
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005228 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5229 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005230 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005231 }
5232
5233 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005234 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005235 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005236 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5237 if (!changed)
5238 changed = test_and_clear_bit(HCI_HS_ENABLED,
5239 &hdev->dev_flags);
5240 else
5241 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005242 }
5243
5244 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5245
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005246 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005247 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005248
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005249 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005250 sock_put(match.sk);
5251
Johan Hedberg890ea892013-03-15 17:06:52 -05005252 hci_req_init(&req, hdev);
5253
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005254 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005255 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005256 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005257 clear_eir(&req);
5258
5259 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005260}
5261
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005262void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5263{
5264 struct cmd_lookup match = { NULL, hdev };
5265 bool changed = false;
5266
5267 if (status) {
5268 u8 mgmt_err = mgmt_status(status);
5269
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005270 if (enable) {
5271 if (test_and_clear_bit(HCI_SC_ENABLED,
5272 &hdev->dev_flags))
5273 new_settings(hdev, NULL);
5274 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5275 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005276
5277 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5278 cmd_status_rsp, &mgmt_err);
5279 return;
5280 }
5281
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005282 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005283 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005284 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005285 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005286 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5287 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005288
5289 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5290 settings_rsp, &match);
5291
5292 if (changed)
5293 new_settings(hdev, match.sk);
5294
5295 if (match.sk)
5296 sock_put(match.sk);
5297}
5298
Johan Hedberg92da6092013-03-15 17:06:55 -05005299static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005300{
5301 struct cmd_lookup *match = data;
5302
Johan Hedberg90e70452012-02-23 23:09:40 +02005303 if (match->sk == NULL) {
5304 match->sk = cmd->sk;
5305 sock_hold(match->sk);
5306 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005307}
5308
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005309void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5310 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005311{
Johan Hedberg90e70452012-02-23 23:09:40 +02005312 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005313
Johan Hedberg92da6092013-03-15 17:06:55 -05005314 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5315 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5316 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005317
5318 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005319 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5320 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005321
5322 if (match.sk)
5323 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005324}
5325
Marcel Holtmann7667da32013-10-15 14:26:27 -07005326void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005327{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005328 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005329 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005330
Johan Hedberg13928972013-03-15 17:07:00 -05005331 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005332 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005333
5334 memset(&ev, 0, sizeof(ev));
5335 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005336 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005337
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005338 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005339 if (!cmd) {
5340 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005341
Johan Hedberg13928972013-03-15 17:07:00 -05005342 /* If this is a HCI command related to powering on the
5343 * HCI dev don't send any mgmt signals.
5344 */
5345 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005346 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005347 }
5348
Marcel Holtmann7667da32013-10-15 14:26:27 -07005349 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5350 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005351}
Szymon Jancc35938b2011-03-22 13:12:21 +01005352
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005353void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5354 u8 *randomizer192, u8 *hash256,
5355 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005356{
5357 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005358
Johan Hedberg744cf192011-11-08 20:40:14 +02005359 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005360
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005361 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005362 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005363 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005364
5365 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005366 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5367 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005368 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005369 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5370 hash256 && randomizer256) {
5371 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005372
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005373 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5374 memcpy(rp.randomizer192, randomizer192,
5375 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005376
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005377 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5378 memcpy(rp.randomizer256, randomizer256,
5379 sizeof(rp.randomizer256));
5380
5381 cmd_complete(cmd->sk, hdev->id,
5382 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5383 &rp, sizeof(rp));
5384 } else {
5385 struct mgmt_rp_read_local_oob_data rp;
5386
5387 memcpy(rp.hash, hash192, sizeof(rp.hash));
5388 memcpy(rp.randomizer, randomizer192,
5389 sizeof(rp.randomizer));
5390
5391 cmd_complete(cmd->sk, hdev->id,
5392 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5393 &rp, sizeof(rp));
5394 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005395 }
5396
5397 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005398}
Johan Hedberge17acd42011-03-30 23:57:16 +03005399
Marcel Holtmann901801b2013-10-06 23:55:51 -07005400void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5401 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
5402 ssp, u8 *eir, u16 eir_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005403{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005404 char buf[512];
5405 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005406 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005407 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005408
Andre Guedes12602d02013-04-30 15:29:40 -03005409 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005410 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005411
Johan Hedberg1dc06092012-01-15 21:01:23 +02005412 /* Leave 5 bytes for a potential CoD field */
5413 if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005414 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005415
Johan Hedberg1dc06092012-01-15 21:01:23 +02005416 memset(buf, 0, sizeof(buf));
5417
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005418 irk = hci_get_irk(hdev, bdaddr, addr_type);
5419 if (irk) {
5420 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5421 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5422 } else {
5423 bacpy(&ev->addr.bdaddr, bdaddr);
5424 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5425 }
5426
Johan Hedberge319d2e2012-01-15 19:51:59 +02005427 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005428 if (cfm_name)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305429 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005430 if (!ssp)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305431 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005432
Johan Hedberg1dc06092012-01-15 21:01:23 +02005433 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005434 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005435
Johan Hedberg1dc06092012-01-15 21:01:23 +02005436 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5437 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005438 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005439
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005440 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005441 ev_size = sizeof(*ev) + eir_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005442
Marcel Holtmann901801b2013-10-06 23:55:51 -07005443 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005444}
Johan Hedberga88a9652011-03-30 13:18:12 +03005445
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005446void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5447 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005448{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005449 struct mgmt_ev_device_found *ev;
5450 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5451 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005452
Johan Hedbergb644ba32012-01-17 21:48:47 +02005453 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005454
Johan Hedbergb644ba32012-01-17 21:48:47 +02005455 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005456
Johan Hedbergb644ba32012-01-17 21:48:47 +02005457 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005458 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005459 ev->rssi = rssi;
5460
5461 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005462 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005463
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005464 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005465
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005466 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005467}
Johan Hedberg314b2382011-04-27 10:29:57 -04005468
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005469void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005470{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005471 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005472 struct pending_cmd *cmd;
5473
Andre Guedes343fb142011-11-22 17:14:19 -03005474 BT_DBG("%s discovering %u", hdev->name, discovering);
5475
Johan Hedberg164a6e72011-11-01 17:06:44 +02005476 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005477 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005478 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005479 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005480
5481 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005482 u8 type = hdev->discovery.type;
5483
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005484 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5485 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005486 mgmt_pending_remove(cmd);
5487 }
5488
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005489 memset(&ev, 0, sizeof(ev));
5490 ev.type = hdev->discovery.type;
5491 ev.discovering = discovering;
5492
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005493 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04005494}
Antti Julku5e762442011-08-25 16:48:02 +03005495
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005496int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005497{
5498 struct pending_cmd *cmd;
5499 struct mgmt_ev_device_blocked ev;
5500
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005501 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005502
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005503 bacpy(&ev.addr.bdaddr, bdaddr);
5504 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005505
Johan Hedberg744cf192011-11-08 20:40:14 +02005506 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005507 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005508}
5509
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005510int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005511{
5512 struct pending_cmd *cmd;
5513 struct mgmt_ev_device_unblocked ev;
5514
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005515 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005516
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005517 bacpy(&ev.addr.bdaddr, bdaddr);
5518 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005519
Johan Hedberg744cf192011-11-08 20:40:14 +02005520 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005521 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005522}
Marcel Holtmann5976e602013-10-06 04:08:14 -07005523
5524static void adv_enable_complete(struct hci_dev *hdev, u8 status)
5525{
5526 BT_DBG("%s status %u", hdev->name, status);
5527
5528 /* Clear the advertising mgmt setting if we failed to re-enable it */
5529 if (status) {
5530 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005531 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005532 }
5533}
5534
5535void mgmt_reenable_advertising(struct hci_dev *hdev)
5536{
5537 struct hci_request req;
5538
Marcel Holtmannb145edc2013-10-10 09:47:54 -07005539 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07005540 return;
5541
5542 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5543 return;
5544
5545 hci_req_init(&req, hdev);
5546 enable_advertising(&req);
5547
5548 /* If this fails we have no option but to let user space know
5549 * that we've disabled advertising.
5550 */
5551 if (hci_req_run(&req, adv_enable_complete) < 0) {
5552 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005553 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005554 }
5555}