blob: 73b6ff817796a6538921cfec8ba50095f8e3cc42 [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 Hedberg62b04cd2014-02-23 19:42:27 +020084 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020085 MGMT_OP_LOAD_IRKS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020086};
87
88static const u16 mgmt_events[] = {
89 MGMT_EV_CONTROLLER_ERROR,
90 MGMT_EV_INDEX_ADDED,
91 MGMT_EV_INDEX_REMOVED,
92 MGMT_EV_NEW_SETTINGS,
93 MGMT_EV_CLASS_OF_DEV_CHANGED,
94 MGMT_EV_LOCAL_NAME_CHANGED,
95 MGMT_EV_NEW_LINK_KEY,
96 MGMT_EV_NEW_LONG_TERM_KEY,
97 MGMT_EV_DEVICE_CONNECTED,
98 MGMT_EV_DEVICE_DISCONNECTED,
99 MGMT_EV_CONNECT_FAILED,
100 MGMT_EV_PIN_CODE_REQUEST,
101 MGMT_EV_USER_CONFIRM_REQUEST,
102 MGMT_EV_USER_PASSKEY_REQUEST,
103 MGMT_EV_AUTH_FAILED,
104 MGMT_EV_DEVICE_FOUND,
105 MGMT_EV_DISCOVERING,
106 MGMT_EV_DEVICE_BLOCKED,
107 MGMT_EV_DEVICE_UNBLOCKED,
108 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300109 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800110 MGMT_EV_NEW_IRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200111};
112
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800113#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200114
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200115#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
116 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
117
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200118struct pending_cmd {
119 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200120 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200121 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100122 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200123 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300124 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200125};
126
Johan Hedbergca69b792011-11-11 18:10:00 +0200127/* HCI to MGMT error code conversion table */
128static u8 mgmt_status_table[] = {
129 MGMT_STATUS_SUCCESS,
130 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
131 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
132 MGMT_STATUS_FAILED, /* Hardware Failure */
133 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
134 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200135 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200136 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
137 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
138 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
139 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
140 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
141 MGMT_STATUS_BUSY, /* Command Disallowed */
142 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
143 MGMT_STATUS_REJECTED, /* Rejected Security */
144 MGMT_STATUS_REJECTED, /* Rejected Personal */
145 MGMT_STATUS_TIMEOUT, /* Host Timeout */
146 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
147 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
148 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
149 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
150 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
151 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
152 MGMT_STATUS_BUSY, /* Repeated Attempts */
153 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
154 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
155 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
156 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
157 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
158 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
159 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
160 MGMT_STATUS_FAILED, /* Unspecified Error */
161 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
162 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
163 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
164 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
165 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
166 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
167 MGMT_STATUS_FAILED, /* Unit Link Key Used */
168 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
169 MGMT_STATUS_TIMEOUT, /* Instant Passed */
170 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
171 MGMT_STATUS_FAILED, /* Transaction Collision */
172 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
173 MGMT_STATUS_REJECTED, /* QoS Rejected */
174 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
175 MGMT_STATUS_REJECTED, /* Insufficient Security */
176 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
177 MGMT_STATUS_BUSY, /* Role Switch Pending */
178 MGMT_STATUS_FAILED, /* Slot Violation */
179 MGMT_STATUS_FAILED, /* Role Switch Failed */
180 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
181 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
182 MGMT_STATUS_BUSY, /* Host Busy Pairing */
183 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
184 MGMT_STATUS_BUSY, /* Controller Busy */
185 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
186 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
187 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
188 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
189 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
190};
191
192static u8 mgmt_status(u8 hci_status)
193{
194 if (hci_status < ARRAY_SIZE(mgmt_status_table))
195 return mgmt_status_table[hci_status];
196
197 return MGMT_STATUS_FAILED;
198}
199
Szymon Janc4e51eae2011-02-25 19:05:48 +0100200static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200201{
202 struct sk_buff *skb;
203 struct mgmt_hdr *hdr;
204 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300205 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200206
Szymon Janc34eb5252011-02-28 14:10:08 +0100207 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200208
Andre Guedes790eff42012-06-07 19:05:46 -0300209 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200210 if (!skb)
211 return -ENOMEM;
212
213 hdr = (void *) skb_put(skb, sizeof(*hdr));
214
Syam Sidhardhan612dfce2012-10-29 22:37:36 +0530215 hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100216 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200217 hdr->len = cpu_to_le16(sizeof(*ev));
218
219 ev = (void *) skb_put(skb, sizeof(*ev));
220 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200221 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200222
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300223 err = sock_queue_rcv_skb(sk, skb);
224 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200225 kfree_skb(skb);
226
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300227 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200228}
229
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200230static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300231 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200232{
233 struct sk_buff *skb;
234 struct mgmt_hdr *hdr;
235 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300236 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200237
238 BT_DBG("sock %p", sk);
239
Andre Guedes790eff42012-06-07 19:05:46 -0300240 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200241 if (!skb)
242 return -ENOMEM;
243
244 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200245
Syam Sidhardhan612dfce2012-10-29 22:37:36 +0530246 hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200248 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200249
Johan Hedberga38528f2011-01-22 06:46:43 +0200250 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200251 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200252 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100253
254 if (rp)
255 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200256
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300257 err = sock_queue_rcv_skb(sk, skb);
258 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200259 kfree_skb(skb);
260
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100261 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200262}
263
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300264static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
265 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200266{
267 struct mgmt_rp_read_version rp;
268
269 BT_DBG("sock %p", sk);
270
271 rp.version = MGMT_VERSION;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200272 rp.revision = __constant_cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200273
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200274 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300275 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200276}
277
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
279 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200280{
281 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200282 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
283 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200284 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200285 size_t rp_size;
286 int i, err;
287
288 BT_DBG("sock %p", sk);
289
290 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
291
292 rp = kmalloc(rp_size, GFP_KERNEL);
293 if (!rp)
294 return -ENOMEM;
295
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200296 rp->num_commands = __constant_cpu_to_le16(num_commands);
297 rp->num_events = __constant_cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200298
299 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
300 put_unaligned_le16(mgmt_commands[i], opcode);
301
302 for (i = 0; i < num_events; i++, opcode++)
303 put_unaligned_le16(mgmt_events[i], opcode);
304
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200305 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300306 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200307 kfree(rp);
308
309 return err;
310}
311
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300312static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
313 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200314{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200315 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200316 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200317 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200318 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300319 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200320
321 BT_DBG("sock %p", sk);
322
323 read_lock(&hci_dev_list_lock);
324
325 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300326 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700327 if (d->dev_type == HCI_BREDR)
328 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200329 }
330
Johan Hedberga38528f2011-01-22 06:46:43 +0200331 rp_len = sizeof(*rp) + (2 * count);
332 rp = kmalloc(rp_len, GFP_ATOMIC);
333 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100334 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200335 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100336 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200337
Johan Hedberg476e44c2012-10-19 20:10:46 +0300338 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200339 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200340 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200341 continue;
342
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700343 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
344 continue;
345
Marcel Holtmann1514b892013-10-06 08:25:01 -0700346 if (d->dev_type == HCI_BREDR) {
347 rp->index[count++] = cpu_to_le16(d->id);
348 BT_DBG("Added hci%u", d->id);
349 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200350 }
351
Johan Hedberg476e44c2012-10-19 20:10:46 +0300352 rp->num_controllers = cpu_to_le16(count);
353 rp_len = sizeof(*rp) + (2 * count);
354
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200355 read_unlock(&hci_dev_list_lock);
356
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200357 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300358 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200359
Johan Hedberga38528f2011-01-22 06:46:43 +0200360 kfree(rp);
361
362 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363}
364
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200365static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200366{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200367 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200368
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200369 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200370 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800371 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200372
Andre Guedesed3fa312012-07-24 15:03:46 -0300373 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300374 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500375 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
376 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300377 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200378 settings |= MGMT_SETTING_BREDR;
379 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700380
381 if (lmp_ssp_capable(hdev)) {
382 settings |= MGMT_SETTING_SSP;
383 settings |= MGMT_SETTING_HS;
384 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800385
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800386 if (lmp_sc_capable(hdev) ||
387 test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800388 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700389 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100390
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300391 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200392 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300393 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200394 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300395 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200396
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200397 return settings;
398}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200399
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200400static u32 get_current_settings(struct hci_dev *hdev)
401{
402 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200403
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200404 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100405 settings |= MGMT_SETTING_POWERED;
406
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200407 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200408 settings |= MGMT_SETTING_CONNECTABLE;
409
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500410 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
411 settings |= MGMT_SETTING_FAST_CONNECTABLE;
412
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200413 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200414 settings |= MGMT_SETTING_DISCOVERABLE;
415
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200416 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200417 settings |= MGMT_SETTING_PAIRABLE;
418
Johan Hedberg56f87902013-10-02 13:43:13 +0300419 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200420 settings |= MGMT_SETTING_BREDR;
421
Johan Hedberg06199cf2012-02-22 16:37:11 +0200422 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200423 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200424
Johan Hedberg47990ea2012-02-22 11:58:37 +0200425 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200426 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200427
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200428 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200430
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200431 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
432 settings |= MGMT_SETTING_HS;
433
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200434 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300435 settings |= MGMT_SETTING_ADVERTISING;
436
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800437 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
438 settings |= MGMT_SETTING_SECURE_CONN;
439
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800440 if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags))
441 settings |= MGMT_SETTING_DEBUG_KEYS;
442
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200443 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
444 settings |= MGMT_SETTING_PRIVACY;
445
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200446 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200447}
448
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300449#define PNP_INFO_SVCLASS_ID 0x1200
450
Johan Hedberg213202e2013-01-27 00:31:33 +0200451static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
452{
453 u8 *ptr = data, *uuids_start = NULL;
454 struct bt_uuid *uuid;
455
456 if (len < 4)
457 return ptr;
458
459 list_for_each_entry(uuid, &hdev->uuids, list) {
460 u16 uuid16;
461
462 if (uuid->size != 16)
463 continue;
464
465 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
466 if (uuid16 < 0x1100)
467 continue;
468
469 if (uuid16 == PNP_INFO_SVCLASS_ID)
470 continue;
471
472 if (!uuids_start) {
473 uuids_start = ptr;
474 uuids_start[0] = 1;
475 uuids_start[1] = EIR_UUID16_ALL;
476 ptr += 2;
477 }
478
479 /* Stop if not enough space to put next UUID */
480 if ((ptr - data) + sizeof(u16) > len) {
481 uuids_start[1] = EIR_UUID16_SOME;
482 break;
483 }
484
485 *ptr++ = (uuid16 & 0x00ff);
486 *ptr++ = (uuid16 & 0xff00) >> 8;
487 uuids_start[0] += sizeof(uuid16);
488 }
489
490 return ptr;
491}
492
Johan Hedbergcdf19632013-01-27 00:31:34 +0200493static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
494{
495 u8 *ptr = data, *uuids_start = NULL;
496 struct bt_uuid *uuid;
497
498 if (len < 6)
499 return ptr;
500
501 list_for_each_entry(uuid, &hdev->uuids, list) {
502 if (uuid->size != 32)
503 continue;
504
505 if (!uuids_start) {
506 uuids_start = ptr;
507 uuids_start[0] = 1;
508 uuids_start[1] = EIR_UUID32_ALL;
509 ptr += 2;
510 }
511
512 /* Stop if not enough space to put next UUID */
513 if ((ptr - data) + sizeof(u32) > len) {
514 uuids_start[1] = EIR_UUID32_SOME;
515 break;
516 }
517
518 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
519 ptr += sizeof(u32);
520 uuids_start[0] += sizeof(u32);
521 }
522
523 return ptr;
524}
525
Johan Hedbergc00d5752013-01-27 00:31:35 +0200526static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
527{
528 u8 *ptr = data, *uuids_start = NULL;
529 struct bt_uuid *uuid;
530
531 if (len < 18)
532 return ptr;
533
534 list_for_each_entry(uuid, &hdev->uuids, list) {
535 if (uuid->size != 128)
536 continue;
537
538 if (!uuids_start) {
539 uuids_start = ptr;
540 uuids_start[0] = 1;
541 uuids_start[1] = EIR_UUID128_ALL;
542 ptr += 2;
543 }
544
545 /* Stop if not enough space to put next UUID */
546 if ((ptr - data) + 16 > len) {
547 uuids_start[1] = EIR_UUID128_SOME;
548 break;
549 }
550
551 memcpy(ptr, uuid->uuid, 16);
552 ptr += 16;
553 uuids_start[0] += 16;
554 }
555
556 return ptr;
557}
558
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300559static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
560{
561 struct pending_cmd *cmd;
562
563 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
564 if (cmd->opcode == opcode)
565 return cmd;
566 }
567
568 return NULL;
569}
570
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700571static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
572{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700573 u8 ad_len = 0;
574 size_t name_len;
575
576 name_len = strlen(hdev->dev_name);
577 if (name_len > 0) {
578 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
579
580 if (name_len > max_len) {
581 name_len = max_len;
582 ptr[1] = EIR_NAME_SHORT;
583 } else
584 ptr[1] = EIR_NAME_COMPLETE;
585
586 ptr[0] = name_len + 1;
587
588 memcpy(ptr + 2, hdev->dev_name, name_len);
589
590 ad_len += (name_len + 2);
591 ptr += (name_len + 2);
592 }
593
594 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700595}
596
597static void update_scan_rsp_data(struct hci_request *req)
598{
599 struct hci_dev *hdev = req->hdev;
600 struct hci_cp_le_set_scan_rsp_data cp;
601 u8 len;
602
Johan Hedberg7751ef12013-10-19 23:38:15 +0300603 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700604 return;
605
606 memset(&cp, 0, sizeof(cp));
607
608 len = create_scan_rsp_data(hdev, cp.data);
609
Johan Hedbergeb438b52013-10-16 15:31:07 +0300610 if (hdev->scan_rsp_data_len == len &&
611 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700612 return;
613
Johan Hedbergeb438b52013-10-16 15:31:07 +0300614 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
615 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700616
617 cp.length = len;
618
619 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
620}
621
Johan Hedberg9a43e252013-10-20 19:00:07 +0300622static u8 get_adv_discov_flags(struct hci_dev *hdev)
623{
624 struct pending_cmd *cmd;
625
626 /* If there's a pending mgmt command the flags will not yet have
627 * their final values, so check for this first.
628 */
629 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
630 if (cmd) {
631 struct mgmt_mode *cp = cmd->param;
632 if (cp->val == 0x01)
633 return LE_AD_GENERAL;
634 else if (cp->val == 0x02)
635 return LE_AD_LIMITED;
636 } else {
637 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
638 return LE_AD_LIMITED;
639 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
640 return LE_AD_GENERAL;
641 }
642
643 return 0;
644}
645
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700646static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700647{
648 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700649
Johan Hedberg9a43e252013-10-20 19:00:07 +0300650 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700651
Johan Hedberge8340042014-01-30 11:16:50 -0800652 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700653 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700654
655 if (flags) {
656 BT_DBG("adv flags 0x%02x", flags);
657
658 ptr[0] = 2;
659 ptr[1] = EIR_FLAGS;
660 ptr[2] = flags;
661
662 ad_len += 3;
663 ptr += 3;
664 }
665
666 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
667 ptr[0] = 2;
668 ptr[1] = EIR_TX_POWER;
669 ptr[2] = (u8) hdev->adv_tx_power;
670
671 ad_len += 3;
672 ptr += 3;
673 }
674
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700675 return ad_len;
676}
677
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700678static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700679{
680 struct hci_dev *hdev = req->hdev;
681 struct hci_cp_le_set_adv_data cp;
682 u8 len;
683
Johan Hedberg10994ce2013-10-19 23:38:16 +0300684 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700685 return;
686
687 memset(&cp, 0, sizeof(cp));
688
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700689 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700690
691 if (hdev->adv_data_len == len &&
692 memcmp(cp.data, hdev->adv_data, len) == 0)
693 return;
694
695 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
696 hdev->adv_data_len = len;
697
698 cp.length = len;
699
700 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
701}
702
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300703static void create_eir(struct hci_dev *hdev, u8 *data)
704{
705 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300706 size_t name_len;
707
708 name_len = strlen(hdev->dev_name);
709
710 if (name_len > 0) {
711 /* EIR Data type */
712 if (name_len > 48) {
713 name_len = 48;
714 ptr[1] = EIR_NAME_SHORT;
715 } else
716 ptr[1] = EIR_NAME_COMPLETE;
717
718 /* EIR Data length */
719 ptr[0] = name_len + 1;
720
721 memcpy(ptr + 2, hdev->dev_name, name_len);
722
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300723 ptr += (name_len + 2);
724 }
725
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100726 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700727 ptr[0] = 2;
728 ptr[1] = EIR_TX_POWER;
729 ptr[2] = (u8) hdev->inq_tx_power;
730
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700731 ptr += 3;
732 }
733
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700734 if (hdev->devid_source > 0) {
735 ptr[0] = 9;
736 ptr[1] = EIR_DEVICE_ID;
737
738 put_unaligned_le16(hdev->devid_source, ptr + 2);
739 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
740 put_unaligned_le16(hdev->devid_product, ptr + 6);
741 put_unaligned_le16(hdev->devid_version, ptr + 8);
742
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700743 ptr += 10;
744 }
745
Johan Hedberg213202e2013-01-27 00:31:33 +0200746 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200747 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200748 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300749}
750
Johan Hedberg890ea892013-03-15 17:06:52 -0500751static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300752{
Johan Hedberg890ea892013-03-15 17:06:52 -0500753 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300754 struct hci_cp_write_eir cp;
755
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200756 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500757 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200758
Johan Hedberg976eb202012-10-24 21:12:01 +0300759 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500760 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300761
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200762 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500763 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300764
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200765 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500766 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300767
768 memset(&cp, 0, sizeof(cp));
769
770 create_eir(hdev, cp.data);
771
772 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500773 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300774
775 memcpy(hdev->eir, cp.data, sizeof(cp.data));
776
Johan Hedberg890ea892013-03-15 17:06:52 -0500777 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300778}
779
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200780static u8 get_service_classes(struct hci_dev *hdev)
781{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300782 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200783 u8 val = 0;
784
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300785 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200786 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200787
788 return val;
789}
790
Johan Hedberg890ea892013-03-15 17:06:52 -0500791static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200792{
Johan Hedberg890ea892013-03-15 17:06:52 -0500793 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200794 u8 cod[3];
795
796 BT_DBG("%s", hdev->name);
797
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200798 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500799 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200800
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300801 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
802 return;
803
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200804 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500805 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200806
807 cod[0] = hdev->minor_class;
808 cod[1] = hdev->major_class;
809 cod[2] = get_service_classes(hdev);
810
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700811 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
812 cod[1] |= 0x20;
813
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200814 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500815 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200816
Johan Hedberg890ea892013-03-15 17:06:52 -0500817 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200818}
819
Johan Hedberga4858cb2014-02-25 19:56:31 +0200820static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200821{
822 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200823
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;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200830 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200831 }
832
Johan Hedberga4858cb2014-02-25 19:56:31 +0200833 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200834}
835
836static void enable_advertising(struct hci_request *req)
837{
838 struct hci_dev *hdev = req->hdev;
839 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200840 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200841 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200842
Johan Hedberga4858cb2014-02-25 19:56:31 +0200843 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200844
Johan Hedberga4858cb2014-02-25 19:56:31 +0200845 /* Set require_privacy to true only when non-connectable
846 * advertising is used. In that case it is fine to use a
847 * non-resolvable private address.
848 */
849 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200850 return;
851
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800852 memset(&cp, 0, sizeof(cp));
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200853 cp.min_interval = __constant_cpu_to_le16(0x0800);
854 cp.max_interval = __constant_cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200855 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200856 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200857 cp.channel_map = hdev->le_adv_channel_map;
858
859 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
860
861 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
862}
863
864static void disable_advertising(struct hci_request *req)
865{
866 u8 enable = 0x00;
867
868 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
869}
870
Johan Hedberg7d785252011-12-15 00:47:39 +0200871static void service_cache_off(struct work_struct *work)
872{
873 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300874 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500875 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200876
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200877 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200878 return;
879
Johan Hedberg890ea892013-03-15 17:06:52 -0500880 hci_req_init(&req, hdev);
881
Johan Hedberg7d785252011-12-15 00:47:39 +0200882 hci_dev_lock(hdev);
883
Johan Hedberg890ea892013-03-15 17:06:52 -0500884 update_eir(&req);
885 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200886
887 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500888
889 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200890}
891
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200892static void rpa_expired(struct work_struct *work)
893{
894 struct hci_dev *hdev = container_of(work, struct hci_dev,
895 rpa_expired.work);
896 struct hci_request req;
897
898 BT_DBG("");
899
900 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
901
902 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
903 hci_conn_num(hdev, LE_LINK) > 0)
904 return;
905
906 /* The generation of a new RPA and programming it into the
907 * controller happens in the enable_advertising() function.
908 */
909
910 hci_req_init(&req, hdev);
911
912 disable_advertising(&req);
913 enable_advertising(&req);
914
915 hci_req_run(&req, NULL);
916}
917
Johan Hedberg6a919082012-02-28 06:17:26 +0200918static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200919{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200920 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200921 return;
922
Johan Hedberg4f87da82012-03-02 19:55:56 +0200923 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200924 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200925
Johan Hedberg4f87da82012-03-02 19:55:56 +0200926 /* Non-mgmt controlled devices get this bit set
927 * implicitly so that pairing works for them, however
928 * for mgmt we require user-space to explicitly enable
929 * it
930 */
931 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200932}
933
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200934static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300935 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200936{
937 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200938
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200939 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200940
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300941 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200942
Johan Hedberg03811012010-12-08 00:21:06 +0200943 memset(&rp, 0, sizeof(rp));
944
Johan Hedberg03811012010-12-08 00:21:06 +0200945 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200946
947 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200948 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200949
950 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
951 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
952
953 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200954
955 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200956 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200957
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300958 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200959
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200960 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300961 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200962}
963
964static void mgmt_pending_free(struct pending_cmd *cmd)
965{
966 sock_put(cmd->sk);
967 kfree(cmd->param);
968 kfree(cmd);
969}
970
971static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300972 struct hci_dev *hdev, void *data,
973 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200974{
975 struct pending_cmd *cmd;
976
Andre Guedes12b94562012-06-07 19:05:45 -0300977 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200978 if (!cmd)
979 return NULL;
980
981 cmd->opcode = opcode;
982 cmd->index = hdev->id;
983
Andre Guedes12b94562012-06-07 19:05:45 -0300984 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200985 if (!cmd->param) {
986 kfree(cmd);
987 return NULL;
988 }
989
990 if (data)
991 memcpy(cmd->param, data, len);
992
993 cmd->sk = sk;
994 sock_hold(sk);
995
996 list_add(&cmd->list, &hdev->mgmt_pending);
997
998 return cmd;
999}
1000
1001static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001002 void (*cb)(struct pending_cmd *cmd,
1003 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001004 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001005{
Andre Guedesa3d09352013-02-01 11:21:30 -03001006 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001007
Andre Guedesa3d09352013-02-01 11:21:30 -03001008 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001009 if (opcode > 0 && cmd->opcode != opcode)
1010 continue;
1011
1012 cb(cmd, data);
1013 }
1014}
1015
Johan Hedberg03811012010-12-08 00:21:06 +02001016static void mgmt_pending_remove(struct pending_cmd *cmd)
1017{
1018 list_del(&cmd->list);
1019 mgmt_pending_free(cmd);
1020}
1021
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001022static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001023{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001024 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001025
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001026 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001027 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001028}
1029
Johan Hedberg8b064a32014-02-24 14:52:22 +02001030static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1031{
1032 BT_DBG("%s status 0x%02x", hdev->name, status);
1033
1034 if (hci_conn_count(hdev) == 0)
1035 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1036}
1037
1038static int clean_up_hci_state(struct hci_dev *hdev)
1039{
1040 struct hci_request req;
1041 struct hci_conn *conn;
1042
1043 hci_req_init(&req, hdev);
1044
1045 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1046 test_bit(HCI_PSCAN, &hdev->flags)) {
1047 u8 scan = 0x00;
1048 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1049 }
1050
1051 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1052 disable_advertising(&req);
1053
1054 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Andre Guedesb1efcc22014-02-26 20:21:40 -03001055 hci_req_add_le_scan_disable(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001056 }
1057
1058 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1059 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001060 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001061
Johan Hedbergc9910d02014-02-27 14:35:12 +02001062 switch (conn->state) {
1063 case BT_CONNECTED:
1064 case BT_CONFIG:
1065 dc.handle = cpu_to_le16(conn->handle);
1066 dc.reason = 0x15; /* Terminated due to Power Off */
1067 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1068 break;
1069 case BT_CONNECT:
1070 if (conn->type == LE_LINK)
1071 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1072 0, NULL);
1073 else if (conn->type == ACL_LINK)
1074 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1075 6, &conn->dst);
1076 break;
1077 case BT_CONNECT2:
1078 bacpy(&rej.bdaddr, &conn->dst);
1079 rej.reason = 0x15; /* Terminated due to Power Off */
1080 if (conn->type == ACL_LINK)
1081 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1082 sizeof(rej), &rej);
1083 else if (conn->type == SCO_LINK)
1084 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1085 sizeof(rej), &rej);
1086 break;
1087 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001088 }
1089
1090 return hci_req_run(&req, clean_up_hci_complete);
1091}
1092
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001093static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001094 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001095{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001096 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001097 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001098 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001099
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001100 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001101
Johan Hedberga7e80f22013-01-09 16:05:19 +02001102 if (cp->val != 0x00 && cp->val != 0x01)
1103 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1104 MGMT_STATUS_INVALID_PARAMS);
1105
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001106 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001107
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001108 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1109 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1110 MGMT_STATUS_BUSY);
1111 goto failed;
1112 }
1113
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001114 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1115 cancel_delayed_work(&hdev->power_off);
1116
1117 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001118 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1119 data, len);
1120 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001121 goto failed;
1122 }
1123 }
1124
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001125 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001126 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001127 goto failed;
1128 }
1129
Johan Hedberg03811012010-12-08 00:21:06 +02001130 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1131 if (!cmd) {
1132 err = -ENOMEM;
1133 goto failed;
1134 }
1135
Johan Hedberg8b064a32014-02-24 14:52:22 +02001136 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001137 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001138 err = 0;
1139 } else {
1140 /* Disconnect connections, stop scans, etc */
1141 err = clean_up_hci_state(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001142
Johan Hedberg8b064a32014-02-24 14:52:22 +02001143 /* ENODATA means there were no HCI commands queued */
1144 if (err == -ENODATA) {
1145 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1146 err = 0;
1147 }
1148 }
Johan Hedberg03811012010-12-08 00:21:06 +02001149
1150failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001151 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001152 return err;
1153}
1154
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001155static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1156 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001157{
1158 struct sk_buff *skb;
1159 struct mgmt_hdr *hdr;
1160
Andre Guedes790eff42012-06-07 19:05:46 -03001161 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001162 if (!skb)
1163 return -ENOMEM;
1164
1165 hdr = (void *) skb_put(skb, sizeof(*hdr));
1166 hdr->opcode = cpu_to_le16(event);
1167 if (hdev)
1168 hdr->index = cpu_to_le16(hdev->id);
1169 else
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05301170 hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001171 hdr->len = cpu_to_le16(data_len);
1172
1173 if (data)
1174 memcpy(skb_put(skb, data_len), data, data_len);
1175
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001176 /* Time stamp */
1177 __net_timestamp(skb);
1178
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001179 hci_send_to_control(skb, skip_sk);
1180 kfree_skb(skb);
1181
1182 return 0;
1183}
1184
1185static int new_settings(struct hci_dev *hdev, struct sock *skip)
1186{
1187 __le32 ev;
1188
1189 ev = cpu_to_le32(get_current_settings(hdev));
1190
1191 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1192}
1193
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001194struct cmd_lookup {
1195 struct sock *sk;
1196 struct hci_dev *hdev;
1197 u8 mgmt_status;
1198};
1199
1200static void settings_rsp(struct pending_cmd *cmd, void *data)
1201{
1202 struct cmd_lookup *match = data;
1203
1204 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1205
1206 list_del(&cmd->list);
1207
1208 if (match->sk == NULL) {
1209 match->sk = cmd->sk;
1210 sock_hold(match->sk);
1211 }
1212
1213 mgmt_pending_free(cmd);
1214}
1215
1216static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1217{
1218 u8 *status = data;
1219
1220 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1221 mgmt_pending_remove(cmd);
1222}
1223
Johan Hedberge6fe7982013-10-02 15:45:22 +03001224static u8 mgmt_bredr_support(struct hci_dev *hdev)
1225{
1226 if (!lmp_bredr_capable(hdev))
1227 return MGMT_STATUS_NOT_SUPPORTED;
1228 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1229 return MGMT_STATUS_REJECTED;
1230 else
1231 return MGMT_STATUS_SUCCESS;
1232}
1233
1234static u8 mgmt_le_support(struct hci_dev *hdev)
1235{
1236 if (!lmp_le_capable(hdev))
1237 return MGMT_STATUS_NOT_SUPPORTED;
1238 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1239 return MGMT_STATUS_REJECTED;
1240 else
1241 return MGMT_STATUS_SUCCESS;
1242}
1243
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001244static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1245{
1246 struct pending_cmd *cmd;
1247 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001248 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001249 bool changed;
1250
1251 BT_DBG("status 0x%02x", status);
1252
1253 hci_dev_lock(hdev);
1254
1255 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1256 if (!cmd)
1257 goto unlock;
1258
1259 if (status) {
1260 u8 mgmt_err = mgmt_status(status);
1261 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001262 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001263 goto remove_cmd;
1264 }
1265
1266 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001267 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001268 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1269 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001270
1271 if (hdev->discov_timeout > 0) {
1272 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1273 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1274 to);
1275 }
1276 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001277 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1278 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001279 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001280
1281 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1282
1283 if (changed)
1284 new_settings(hdev, cmd->sk);
1285
Marcel Holtmann970ba522013-10-15 06:33:57 -07001286 /* When the discoverable mode gets changed, make sure
1287 * that class of device has the limited discoverable
1288 * bit correctly set.
1289 */
1290 hci_req_init(&req, hdev);
1291 update_class(&req);
1292 hci_req_run(&req, NULL);
1293
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001294remove_cmd:
1295 mgmt_pending_remove(cmd);
1296
1297unlock:
1298 hci_dev_unlock(hdev);
1299}
1300
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001301static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001302 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001303{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001304 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001305 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001306 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001307 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001308 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001309 int err;
1310
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001311 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001312
Johan Hedberg9a43e252013-10-20 19:00:07 +03001313 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1314 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001315 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001316 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001317
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001318 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001319 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1320 MGMT_STATUS_INVALID_PARAMS);
1321
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001322 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001323
1324 /* Disabling discoverable requires that no timeout is set,
1325 * and enabling limited discoverable requires a timeout.
1326 */
1327 if ((cp->val == 0x00 && timeout > 0) ||
1328 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001329 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001330 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001331
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001332 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001333
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001334 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001335 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001336 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001337 goto failed;
1338 }
1339
1340 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001341 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001342 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001343 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001344 goto failed;
1345 }
1346
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001347 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001348 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001349 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001350 goto failed;
1351 }
1352
1353 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001354 bool changed = false;
1355
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001356 /* Setting limited discoverable when powered off is
1357 * not a valid operation since it requires a timeout
1358 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1359 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001360 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1361 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1362 changed = true;
1363 }
1364
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001365 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001366 if (err < 0)
1367 goto failed;
1368
1369 if (changed)
1370 err = new_settings(hdev, sk);
1371
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001372 goto failed;
1373 }
1374
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001375 /* If the current mode is the same, then just update the timeout
1376 * value with the new value. And if only the timeout gets updated,
1377 * then no need for any HCI transactions.
1378 */
1379 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1380 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1381 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001382 cancel_delayed_work(&hdev->discov_off);
1383 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001384
Marcel Holtmann36261542013-10-15 08:28:51 -07001385 if (cp->val && hdev->discov_timeout > 0) {
1386 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001387 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001388 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001389 }
1390
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001391 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001392 goto failed;
1393 }
1394
1395 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1396 if (!cmd) {
1397 err = -ENOMEM;
1398 goto failed;
1399 }
1400
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001401 /* Cancel any potential discoverable timeout that might be
1402 * still active and store new timeout value. The arming of
1403 * the timeout happens in the complete handler.
1404 */
1405 cancel_delayed_work(&hdev->discov_off);
1406 hdev->discov_timeout = timeout;
1407
Johan Hedbergb456f872013-10-19 23:38:22 +03001408 /* Limited discoverable mode */
1409 if (cp->val == 0x02)
1410 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1411 else
1412 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1413
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001414 hci_req_init(&req, hdev);
1415
Johan Hedberg9a43e252013-10-20 19:00:07 +03001416 /* The procedure for LE-only controllers is much simpler - just
1417 * update the advertising data.
1418 */
1419 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1420 goto update_ad;
1421
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001422 scan = SCAN_PAGE;
1423
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001424 if (cp->val) {
1425 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001426
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001427 if (cp->val == 0x02) {
1428 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001429 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001430 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1431 hci_cp.iac_lap[1] = 0x8b;
1432 hci_cp.iac_lap[2] = 0x9e;
1433 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1434 hci_cp.iac_lap[4] = 0x8b;
1435 hci_cp.iac_lap[5] = 0x9e;
1436 } else {
1437 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001438 hci_cp.num_iac = 1;
1439 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1440 hci_cp.iac_lap[1] = 0x8b;
1441 hci_cp.iac_lap[2] = 0x9e;
1442 }
1443
1444 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1445 (hci_cp.num_iac * 3) + 1, &hci_cp);
1446
1447 scan |= SCAN_INQUIRY;
1448 } else {
1449 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1450 }
1451
1452 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001453
Johan Hedberg9a43e252013-10-20 19:00:07 +03001454update_ad:
1455 update_adv_data(&req);
1456
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001457 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001458 if (err < 0)
1459 mgmt_pending_remove(cmd);
1460
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001461failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001462 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001463 return err;
1464}
1465
Johan Hedberg406d7802013-03-15 17:07:09 -05001466static void write_fast_connectable(struct hci_request *req, bool enable)
1467{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001468 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001469 struct hci_cp_write_page_scan_activity acp;
1470 u8 type;
1471
Johan Hedberg547003b2013-10-21 16:51:53 +03001472 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1473 return;
1474
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001475 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1476 return;
1477
Johan Hedberg406d7802013-03-15 17:07:09 -05001478 if (enable) {
1479 type = PAGE_SCAN_TYPE_INTERLACED;
1480
1481 /* 160 msec page scan interval */
1482 acp.interval = __constant_cpu_to_le16(0x0100);
1483 } else {
1484 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1485
1486 /* default 1.28 sec page scan */
1487 acp.interval = __constant_cpu_to_le16(0x0800);
1488 }
1489
1490 acp.window = __constant_cpu_to_le16(0x0012);
1491
Johan Hedbergbd98b992013-03-15 17:07:13 -05001492 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1493 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1494 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1495 sizeof(acp), &acp);
1496
1497 if (hdev->page_scan_type != type)
1498 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001499}
1500
Johan Hedberg2b76f452013-03-15 17:07:04 -05001501static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1502{
1503 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001504 struct mgmt_mode *cp;
1505 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001506
1507 BT_DBG("status 0x%02x", status);
1508
1509 hci_dev_lock(hdev);
1510
1511 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1512 if (!cmd)
1513 goto unlock;
1514
Johan Hedberg37438c12013-10-14 16:20:05 +03001515 if (status) {
1516 u8 mgmt_err = mgmt_status(status);
1517 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1518 goto remove_cmd;
1519 }
1520
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001521 cp = cmd->param;
1522 if (cp->val)
1523 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1524 else
1525 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1526
Johan Hedberg2b76f452013-03-15 17:07:04 -05001527 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1528
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001529 if (changed)
1530 new_settings(hdev, cmd->sk);
1531
Johan Hedberg37438c12013-10-14 16:20:05 +03001532remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001533 mgmt_pending_remove(cmd);
1534
1535unlock:
1536 hci_dev_unlock(hdev);
1537}
1538
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001539static int set_connectable_update_settings(struct hci_dev *hdev,
1540 struct sock *sk, u8 val)
1541{
1542 bool changed = false;
1543 int err;
1544
1545 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1546 changed = true;
1547
1548 if (val) {
1549 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1550 } else {
1551 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1552 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1553 }
1554
1555 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1556 if (err < 0)
1557 return err;
1558
1559 if (changed)
1560 return new_settings(hdev, sk);
1561
1562 return 0;
1563}
1564
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001565static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001566 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001567{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001568 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001569 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001570 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001571 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001572 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001574 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001575
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001576 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1577 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001578 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001579 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001580
Johan Hedberga7e80f22013-01-09 16:05:19 +02001581 if (cp->val != 0x00 && cp->val != 0x01)
1582 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1583 MGMT_STATUS_INVALID_PARAMS);
1584
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001585 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001586
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001587 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001588 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001589 goto failed;
1590 }
1591
1592 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001593 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001594 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001595 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001596 goto failed;
1597 }
1598
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001599 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1600 if (!cmd) {
1601 err = -ENOMEM;
1602 goto failed;
1603 }
1604
Johan Hedberg2b76f452013-03-15 17:07:04 -05001605 hci_req_init(&req, hdev);
1606
Johan Hedberg9a43e252013-10-20 19:00:07 +03001607 /* If BR/EDR is not enabled and we disable advertising as a
1608 * by-product of disabling connectable, we need to update the
1609 * advertising flags.
1610 */
1611 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1612 if (!cp->val) {
1613 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1614 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1615 }
1616 update_adv_data(&req);
1617 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001618 if (cp->val) {
1619 scan = SCAN_PAGE;
1620 } else {
1621 scan = 0;
1622
1623 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001624 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001625 cancel_delayed_work(&hdev->discov_off);
1626 }
1627
1628 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1629 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001630
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001631 /* If we're going from non-connectable to connectable or
1632 * vice-versa when fast connectable is enabled ensure that fast
1633 * connectable gets disabled. write_fast_connectable won't do
1634 * anything if the page scan parameters are already what they
1635 * should be.
1636 */
1637 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001638 write_fast_connectable(&req, false);
1639
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001640 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1641 hci_conn_num(hdev, LE_LINK) == 0) {
1642 disable_advertising(&req);
1643 enable_advertising(&req);
1644 }
1645
Johan Hedberg2b76f452013-03-15 17:07:04 -05001646 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001647 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001648 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001649 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001650 err = set_connectable_update_settings(hdev, sk,
1651 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001652 goto failed;
1653 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001654
1655failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001656 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001657 return err;
1658}
1659
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001660static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001661 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001662{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001663 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001664 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001665 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001667 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001668
Johan Hedberga7e80f22013-01-09 16:05:19 +02001669 if (cp->val != 0x00 && cp->val != 0x01)
1670 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1671 MGMT_STATUS_INVALID_PARAMS);
1672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001673 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001674
1675 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001676 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001677 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001678 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001679
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001680 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001681 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001682 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001683
Marcel Holtmann55594352013-10-06 16:11:57 -07001684 if (changed)
1685 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001686
Marcel Holtmann55594352013-10-06 16:11:57 -07001687unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001688 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001689 return err;
1690}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001691
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001692static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1693 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001694{
1695 struct mgmt_mode *cp = data;
1696 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001697 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001698 int err;
1699
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001700 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001701
Johan Hedberge6fe7982013-10-02 15:45:22 +03001702 status = mgmt_bredr_support(hdev);
1703 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001704 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001705 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001706
Johan Hedberga7e80f22013-01-09 16:05:19 +02001707 if (cp->val != 0x00 && cp->val != 0x01)
1708 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1709 MGMT_STATUS_INVALID_PARAMS);
1710
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001711 hci_dev_lock(hdev);
1712
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001713 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001714 bool changed = false;
1715
1716 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001717 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001718 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1719 changed = true;
1720 }
1721
1722 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1723 if (err < 0)
1724 goto failed;
1725
1726 if (changed)
1727 err = new_settings(hdev, sk);
1728
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001729 goto failed;
1730 }
1731
1732 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001733 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001734 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001735 goto failed;
1736 }
1737
1738 val = !!cp->val;
1739
1740 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1741 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1742 goto failed;
1743 }
1744
1745 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1746 if (!cmd) {
1747 err = -ENOMEM;
1748 goto failed;
1749 }
1750
1751 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1752 if (err < 0) {
1753 mgmt_pending_remove(cmd);
1754 goto failed;
1755 }
1756
1757failed:
1758 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001759 return err;
1760}
1761
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001762static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001763{
1764 struct mgmt_mode *cp = data;
1765 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001766 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001767 int err;
1768
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001769 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001770
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001771 status = mgmt_bredr_support(hdev);
1772 if (status)
1773 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1774
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001775 if (!lmp_ssp_capable(hdev))
1776 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1777 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001778
Johan Hedberga7e80f22013-01-09 16:05:19 +02001779 if (cp->val != 0x00 && cp->val != 0x01)
1780 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1781 MGMT_STATUS_INVALID_PARAMS);
1782
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001783 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001784
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001785 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001786 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001787
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001788 if (cp->val) {
1789 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1790 &hdev->dev_flags);
1791 } else {
1792 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1793 &hdev->dev_flags);
1794 if (!changed)
1795 changed = test_and_clear_bit(HCI_HS_ENABLED,
1796 &hdev->dev_flags);
1797 else
1798 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001799 }
1800
1801 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1802 if (err < 0)
1803 goto failed;
1804
1805 if (changed)
1806 err = new_settings(hdev, sk);
1807
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001808 goto failed;
1809 }
1810
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001811 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1812 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001813 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1814 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001815 goto failed;
1816 }
1817
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001818 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001819 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1820 goto failed;
1821 }
1822
1823 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1824 if (!cmd) {
1825 err = -ENOMEM;
1826 goto failed;
1827 }
1828
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001829 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001830 if (err < 0) {
1831 mgmt_pending_remove(cmd);
1832 goto failed;
1833 }
1834
1835failed:
1836 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001837 return err;
1838}
1839
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001840static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001841{
1842 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001843 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001844 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001845 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001846
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001847 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001848
Johan Hedberge6fe7982013-10-02 15:45:22 +03001849 status = mgmt_bredr_support(hdev);
1850 if (status)
1851 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001852
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001853 if (!lmp_ssp_capable(hdev))
1854 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1855 MGMT_STATUS_NOT_SUPPORTED);
1856
1857 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1858 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1859 MGMT_STATUS_REJECTED);
1860
Johan Hedberga7e80f22013-01-09 16:05:19 +02001861 if (cp->val != 0x00 && cp->val != 0x01)
1862 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1863 MGMT_STATUS_INVALID_PARAMS);
1864
Marcel Holtmannee392692013-10-01 22:59:23 -07001865 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001866
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001867 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001868 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001869 } else {
1870 if (hdev_is_powered(hdev)) {
1871 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1872 MGMT_STATUS_REJECTED);
1873 goto unlock;
1874 }
1875
Marcel Holtmannee392692013-10-01 22:59:23 -07001876 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001877 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001878
1879 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1880 if (err < 0)
1881 goto unlock;
1882
1883 if (changed)
1884 err = new_settings(hdev, sk);
1885
1886unlock:
1887 hci_dev_unlock(hdev);
1888 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001889}
1890
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001891static void le_enable_complete(struct hci_dev *hdev, u8 status)
1892{
1893 struct cmd_lookup match = { NULL, hdev };
1894
1895 if (status) {
1896 u8 mgmt_err = mgmt_status(status);
1897
1898 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1899 &mgmt_err);
1900 return;
1901 }
1902
1903 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1904
1905 new_settings(hdev, match.sk);
1906
1907 if (match.sk)
1908 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001909
1910 /* Make sure the controller has a good default for
1911 * advertising data. Restrict the update to when LE
1912 * has actually been enabled. During power on, the
1913 * update in powered_update_hci will take care of it.
1914 */
1915 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1916 struct hci_request req;
1917
1918 hci_dev_lock(hdev);
1919
1920 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001921 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001922 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001923 hci_req_run(&req, NULL);
1924
1925 hci_dev_unlock(hdev);
1926 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001927}
1928
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001929static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001930{
1931 struct mgmt_mode *cp = data;
1932 struct hci_cp_write_le_host_supported hci_cp;
1933 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001934 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001935 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001936 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001937
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001938 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001939
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001940 if (!lmp_le_capable(hdev))
1941 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1942 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001943
Johan Hedberga7e80f22013-01-09 16:05:19 +02001944 if (cp->val != 0x00 && cp->val != 0x01)
1945 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1946 MGMT_STATUS_INVALID_PARAMS);
1947
Johan Hedbergc73eee92013-04-19 18:35:21 +03001948 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03001949 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03001950 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1951 MGMT_STATUS_REJECTED);
1952
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001953 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001954
1955 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001956 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001957
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001958 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02001959 bool changed = false;
1960
1961 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1962 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1963 changed = true;
1964 }
1965
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02001966 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
1967 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03001968 changed = true;
1969 }
1970
Johan Hedberg06199cf2012-02-22 16:37:11 +02001971 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1972 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08001973 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001974
1975 if (changed)
1976 err = new_settings(hdev, sk);
1977
Johan Hedberg1de028c2012-02-29 19:55:35 -08001978 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001979 }
1980
Johan Hedberg4375f102013-09-25 13:26:10 +03001981 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
1982 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001983 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001984 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001985 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001986 }
1987
1988 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
1989 if (!cmd) {
1990 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08001991 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001992 }
1993
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001994 hci_req_init(&req, hdev);
1995
Johan Hedberg06199cf2012-02-22 16:37:11 +02001996 memset(&hci_cp, 0, sizeof(hci_cp));
1997
1998 if (val) {
1999 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002000 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002001 } else {
2002 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2003 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002004 }
2005
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002006 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2007 &hci_cp);
2008
2009 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302010 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002011 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002012
Johan Hedberg1de028c2012-02-29 19:55:35 -08002013unlock:
2014 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002015 return err;
2016}
2017
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002018/* This is a helper function to test for pending mgmt commands that can
2019 * cause CoD or EIR HCI commands. We can only allow one such pending
2020 * mgmt command at a time since otherwise we cannot easily track what
2021 * the current values are, will be, and based on that calculate if a new
2022 * HCI command needs to be sent and if yes with what value.
2023 */
2024static bool pending_eir_or_class(struct hci_dev *hdev)
2025{
2026 struct pending_cmd *cmd;
2027
2028 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2029 switch (cmd->opcode) {
2030 case MGMT_OP_ADD_UUID:
2031 case MGMT_OP_REMOVE_UUID:
2032 case MGMT_OP_SET_DEV_CLASS:
2033 case MGMT_OP_SET_POWERED:
2034 return true;
2035 }
2036 }
2037
2038 return false;
2039}
2040
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002041static const u8 bluetooth_base_uuid[] = {
2042 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2043 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2044};
2045
2046static u8 get_uuid_size(const u8 *uuid)
2047{
2048 u32 val;
2049
2050 if (memcmp(uuid, bluetooth_base_uuid, 12))
2051 return 128;
2052
2053 val = get_unaligned_le32(&uuid[12]);
2054 if (val > 0xffff)
2055 return 32;
2056
2057 return 16;
2058}
2059
Johan Hedberg92da6092013-03-15 17:06:55 -05002060static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2061{
2062 struct pending_cmd *cmd;
2063
2064 hci_dev_lock(hdev);
2065
2066 cmd = mgmt_pending_find(mgmt_op, hdev);
2067 if (!cmd)
2068 goto unlock;
2069
2070 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2071 hdev->dev_class, 3);
2072
2073 mgmt_pending_remove(cmd);
2074
2075unlock:
2076 hci_dev_unlock(hdev);
2077}
2078
2079static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2080{
2081 BT_DBG("status 0x%02x", status);
2082
2083 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2084}
2085
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002086static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002087{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002088 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002089 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002090 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002091 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002092 int err;
2093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002094 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002095
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002096 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002097
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002098 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002099 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002100 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002101 goto failed;
2102 }
2103
Andre Guedes92c4c202012-06-07 19:05:44 -03002104 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002105 if (!uuid) {
2106 err = -ENOMEM;
2107 goto failed;
2108 }
2109
2110 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002111 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002112 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002113
Johan Hedbergde66aa62013-01-27 00:31:27 +02002114 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002115
Johan Hedberg890ea892013-03-15 17:06:52 -05002116 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002117
Johan Hedberg890ea892013-03-15 17:06:52 -05002118 update_class(&req);
2119 update_eir(&req);
2120
Johan Hedberg92da6092013-03-15 17:06:55 -05002121 err = hci_req_run(&req, add_uuid_complete);
2122 if (err < 0) {
2123 if (err != -ENODATA)
2124 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002125
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002126 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002127 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002128 goto failed;
2129 }
2130
2131 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002132 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002133 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002134 goto failed;
2135 }
2136
2137 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002138
2139failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002140 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002141 return err;
2142}
2143
Johan Hedberg24b78d02012-02-23 23:24:30 +02002144static bool enable_service_cache(struct hci_dev *hdev)
2145{
2146 if (!hdev_is_powered(hdev))
2147 return false;
2148
2149 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002150 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2151 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002152 return true;
2153 }
2154
2155 return false;
2156}
2157
Johan Hedberg92da6092013-03-15 17:06:55 -05002158static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2159{
2160 BT_DBG("status 0x%02x", status);
2161
2162 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2163}
2164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002165static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002166 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002167{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002168 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002169 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002170 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002171 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 -05002172 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002173 int err, found;
2174
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002175 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002176
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002177 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002178
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002179 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002180 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002181 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002182 goto unlock;
2183 }
2184
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002185 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002186 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002187
Johan Hedberg24b78d02012-02-23 23:24:30 +02002188 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002189 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002190 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002191 goto unlock;
2192 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002193
Johan Hedberg9246a862012-02-23 21:33:16 +02002194 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002195 }
2196
2197 found = 0;
2198
Johan Hedberg056341c2013-01-27 00:31:30 +02002199 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002200 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2201 continue;
2202
2203 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002204 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002205 found++;
2206 }
2207
2208 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002209 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002210 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002211 goto unlock;
2212 }
2213
Johan Hedberg9246a862012-02-23 21:33:16 +02002214update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002215 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002216
Johan Hedberg890ea892013-03-15 17:06:52 -05002217 update_class(&req);
2218 update_eir(&req);
2219
Johan Hedberg92da6092013-03-15 17:06:55 -05002220 err = hci_req_run(&req, remove_uuid_complete);
2221 if (err < 0) {
2222 if (err != -ENODATA)
2223 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002224
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002225 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 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_REMOVE_UUID, 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 Hedberg2aeb9a12011-01-04 12:08:51 +02002237
2238unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002239 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002240 return err;
2241}
2242
Johan Hedberg92da6092013-03-15 17:06:55 -05002243static void set_class_complete(struct hci_dev *hdev, u8 status)
2244{
2245 BT_DBG("status 0x%02x", status);
2246
2247 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2248}
2249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002250static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002251 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002252{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002253 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002254 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002255 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002256 int err;
2257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002258 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002259
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002260 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002261 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2262 MGMT_STATUS_NOT_SUPPORTED);
2263
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002264 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002265
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002266 if (pending_eir_or_class(hdev)) {
2267 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2268 MGMT_STATUS_BUSY);
2269 goto unlock;
2270 }
2271
2272 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2273 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2274 MGMT_STATUS_INVALID_PARAMS);
2275 goto unlock;
2276 }
2277
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002278 hdev->major_class = cp->major;
2279 hdev->minor_class = cp->minor;
2280
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002281 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002282 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002283 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002284 goto unlock;
2285 }
2286
Johan Hedberg890ea892013-03-15 17:06:52 -05002287 hci_req_init(&req, hdev);
2288
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002289 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002290 hci_dev_unlock(hdev);
2291 cancel_delayed_work_sync(&hdev->service_cache);
2292 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002293 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002294 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002295
Johan Hedberg890ea892013-03-15 17:06:52 -05002296 update_class(&req);
2297
Johan Hedberg92da6092013-03-15 17:06:55 -05002298 err = hci_req_run(&req, set_class_complete);
2299 if (err < 0) {
2300 if (err != -ENODATA)
2301 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002302
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002303 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002304 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002305 goto unlock;
2306 }
2307
2308 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002309 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002310 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002311 goto unlock;
2312 }
2313
2314 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002315
Johan Hedbergb5235a62012-02-21 14:32:24 +02002316unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002317 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002318 return err;
2319}
2320
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002321static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002322 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002323{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002324 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002325 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002326 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002327 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002328
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002329 BT_DBG("request for %s", hdev->name);
2330
2331 if (!lmp_bredr_capable(hdev))
2332 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2333 MGMT_STATUS_NOT_SUPPORTED);
2334
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002335 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002336
Johan Hedberg86742e12011-11-07 23:13:38 +02002337 expected_len = sizeof(*cp) + key_count *
2338 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002339 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002340 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002341 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002342 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002343 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002344 }
2345
Johan Hedberg4ae14302013-01-20 14:27:13 +02002346 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2347 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2348 MGMT_STATUS_INVALID_PARAMS);
2349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002350 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002351 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002352
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002353 for (i = 0; i < key_count; i++) {
2354 struct mgmt_link_key_info *key = &cp->keys[i];
2355
Marcel Holtmann8e991132014-01-10 02:07:25 -08002356 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002357 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2358 MGMT_STATUS_INVALID_PARAMS);
2359 }
2360
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002361 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002362
2363 hci_link_keys_clear(hdev);
2364
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002365 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002366 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002367 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002368 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2369
2370 if (changed)
2371 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002372
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002373 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002374 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002375
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002376 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002377 key->type, key->pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002378 }
2379
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002380 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002381
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002382 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002383
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002384 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002385}
2386
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002387static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002388 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002389{
2390 struct mgmt_ev_device_unpaired ev;
2391
2392 bacpy(&ev.addr.bdaddr, bdaddr);
2393 ev.addr.type = addr_type;
2394
2395 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002396 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002397}
2398
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002399static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002400 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002401{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002402 struct mgmt_cp_unpair_device *cp = data;
2403 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002404 struct hci_cp_disconnect dc;
2405 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002406 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002407 int err;
2408
Johan Hedberga8a1d192011-11-10 15:54:38 +02002409 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002410 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2411 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002412
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002413 if (!bdaddr_type_is_valid(cp->addr.type))
2414 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2415 MGMT_STATUS_INVALID_PARAMS,
2416 &rp, sizeof(rp));
2417
Johan Hedberg118da702013-01-20 14:27:20 +02002418 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2419 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2420 MGMT_STATUS_INVALID_PARAMS,
2421 &rp, sizeof(rp));
2422
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002423 hci_dev_lock(hdev);
2424
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002425 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002426 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002427 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002428 goto unlock;
2429 }
2430
Johan Hedberge0b2b272014-02-18 17:14:31 +02002431 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002432 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002433 } else {
2434 u8 addr_type;
2435
2436 if (cp->addr.type == BDADDR_LE_PUBLIC)
2437 addr_type = ADDR_LE_DEV_PUBLIC;
2438 else
2439 addr_type = ADDR_LE_DEV_RANDOM;
2440
Johan Hedberga7ec7332014-02-18 17:14:35 +02002441 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2442
Andre Guedesa9b0a042014-02-26 20:21:52 -03002443 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2444
Johan Hedberge0b2b272014-02-18 17:14:31 +02002445 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2446 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002447
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002448 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002449 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002450 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002451 goto unlock;
2452 }
2453
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002454 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002455 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002456 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002457 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002458 else
2459 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002460 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002461 } else {
2462 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002463 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002464
Johan Hedberga8a1d192011-11-10 15:54:38 +02002465 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002466 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002467 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002468 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002469 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002470 }
2471
Johan Hedberg124f6e32012-02-09 13:50:12 +02002472 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002473 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002474 if (!cmd) {
2475 err = -ENOMEM;
2476 goto unlock;
2477 }
2478
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002479 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002480 dc.reason = 0x13; /* Remote User Terminated Connection */
2481 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2482 if (err < 0)
2483 mgmt_pending_remove(cmd);
2484
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002485unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002486 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002487 return err;
2488}
2489
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002490static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002491 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002492{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002493 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002494 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002495 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002496 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002497 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002498 int err;
2499
2500 BT_DBG("");
2501
Johan Hedberg06a63b12013-01-20 14:27:21 +02002502 memset(&rp, 0, sizeof(rp));
2503 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2504 rp.addr.type = cp->addr.type;
2505
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002506 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002507 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2508 MGMT_STATUS_INVALID_PARAMS,
2509 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002510
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002511 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002512
2513 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002514 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2515 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002516 goto failed;
2517 }
2518
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002519 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002520 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2521 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002522 goto failed;
2523 }
2524
Andre Guedes591f47f2012-04-24 21:02:49 -03002525 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002526 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2527 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002528 else
2529 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002530
Vishal Agarwalf9607272012-06-13 05:32:43 +05302531 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002532 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2533 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002534 goto failed;
2535 }
2536
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002537 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002538 if (!cmd) {
2539 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002540 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002541 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002542
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002543 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002544 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002545
2546 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2547 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002548 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002549
2550failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002551 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002552 return err;
2553}
2554
Andre Guedes57c14772012-04-24 21:02:50 -03002555static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002556{
2557 switch (link_type) {
2558 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002559 switch (addr_type) {
2560 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002561 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002562
Johan Hedberg48264f02011-11-09 13:58:58 +02002563 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002564 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002565 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002566 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002567
Johan Hedberg4c659c32011-11-07 23:13:39 +02002568 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002569 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002570 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002571 }
2572}
2573
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002574static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2575 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002576{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002577 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002578 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002579 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002580 int err;
2581 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002582
2583 BT_DBG("");
2584
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002585 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002586
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002587 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002588 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002589 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002590 goto unlock;
2591 }
2592
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002593 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002594 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2595 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002596 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002597 }
2598
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002599 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002600 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002601 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002602 err = -ENOMEM;
2603 goto unlock;
2604 }
2605
Johan Hedberg2784eb42011-01-21 13:56:35 +02002606 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002607 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002608 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2609 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002610 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002611 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002612 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002613 continue;
2614 i++;
2615 }
2616
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002617 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002618
Johan Hedberg4c659c32011-11-07 23:13:39 +02002619 /* Recalculate length in case of filtered SCO connections, etc */
2620 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002621
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002622 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002623 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002624
Johan Hedberga38528f2011-01-22 06:46:43 +02002625 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002626
2627unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002628 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002629 return err;
2630}
2631
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002632static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002633 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002634{
2635 struct pending_cmd *cmd;
2636 int err;
2637
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002638 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002639 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002640 if (!cmd)
2641 return -ENOMEM;
2642
Johan Hedbergd8457692012-02-17 14:24:57 +02002643 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002644 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002645 if (err < 0)
2646 mgmt_pending_remove(cmd);
2647
2648 return err;
2649}
2650
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002651static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002652 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002653{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002654 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002655 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002656 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002657 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002658 int err;
2659
2660 BT_DBG("");
2661
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002662 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002663
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002664 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002665 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002666 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002667 goto failed;
2668 }
2669
Johan Hedbergd8457692012-02-17 14:24:57 +02002670 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002671 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002672 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002673 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002674 goto failed;
2675 }
2676
2677 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002678 struct mgmt_cp_pin_code_neg_reply ncp;
2679
2680 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002681
2682 BT_ERR("PIN code is not 16 bytes long");
2683
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002684 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002685 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002686 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002687 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002688
2689 goto failed;
2690 }
2691
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002692 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002693 if (!cmd) {
2694 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002695 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002696 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002697
Johan Hedbergd8457692012-02-17 14:24:57 +02002698 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002699 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002700 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002701
2702 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2703 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002704 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002705
2706failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002707 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002708 return err;
2709}
2710
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002711static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2712 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002713{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002714 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002715
2716 BT_DBG("");
2717
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002718 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002719
2720 hdev->io_capability = cp->io_capability;
2721
2722 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002723 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002724
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002725 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002726
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002727 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2728 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002729}
2730
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002731static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002732{
2733 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002734 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002735
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002736 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002737 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2738 continue;
2739
Johan Hedberge9a416b2011-02-19 12:05:56 -03002740 if (cmd->user_data != conn)
2741 continue;
2742
2743 return cmd;
2744 }
2745
2746 return NULL;
2747}
2748
2749static void pairing_complete(struct pending_cmd *cmd, u8 status)
2750{
2751 struct mgmt_rp_pair_device rp;
2752 struct hci_conn *conn = cmd->user_data;
2753
Johan Hedbergba4e5642011-11-11 00:07:34 +02002754 bacpy(&rp.addr.bdaddr, &conn->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002755 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002756
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002757 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002758 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002759
2760 /* So we don't get further callbacks for this connection */
2761 conn->connect_cfm_cb = NULL;
2762 conn->security_cfm_cb = NULL;
2763 conn->disconn_cfm_cb = NULL;
2764
David Herrmann76a68ba2013-04-06 20:28:37 +02002765 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002766
Johan Hedberga664b5b2011-02-19 12:06:02 -03002767 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002768}
2769
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002770void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2771{
2772 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2773 struct pending_cmd *cmd;
2774
2775 cmd = find_pairing(conn);
2776 if (cmd)
2777 pairing_complete(cmd, status);
2778}
2779
Johan Hedberge9a416b2011-02-19 12:05:56 -03002780static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2781{
2782 struct pending_cmd *cmd;
2783
2784 BT_DBG("status %u", status);
2785
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002786 cmd = find_pairing(conn);
2787 if (!cmd)
2788 BT_DBG("Unable to find a pending command");
2789 else
Johan Hedberge2113262012-02-18 15:20:03 +02002790 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002791}
2792
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002793static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302794{
2795 struct pending_cmd *cmd;
2796
2797 BT_DBG("status %u", status);
2798
2799 if (!status)
2800 return;
2801
2802 cmd = find_pairing(conn);
2803 if (!cmd)
2804 BT_DBG("Unable to find a pending command");
2805 else
2806 pairing_complete(cmd, mgmt_status(status));
2807}
2808
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002809static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002810 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002811{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002812 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002813 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002814 struct pending_cmd *cmd;
2815 u8 sec_level, auth_type;
2816 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002817 int err;
2818
2819 BT_DBG("");
2820
Szymon Jancf950a30e2013-01-18 12:48:07 +01002821 memset(&rp, 0, sizeof(rp));
2822 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2823 rp.addr.type = cp->addr.type;
2824
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002825 if (!bdaddr_type_is_valid(cp->addr.type))
2826 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2827 MGMT_STATUS_INVALID_PARAMS,
2828 &rp, sizeof(rp));
2829
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002830 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002831
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002832 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002833 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2834 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002835 goto unlock;
2836 }
2837
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002838 sec_level = BT_SECURITY_MEDIUM;
2839 if (cp->io_cap == 0x03)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002840 auth_type = HCI_AT_DEDICATED_BONDING;
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002841 else
Johan Hedberge9a416b2011-02-19 12:05:56 -03002842 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002843
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002844 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002845 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2846 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002847 } else {
2848 u8 addr_type;
2849
2850 /* Convert from L2CAP channel address type to HCI address type
2851 */
2852 if (cp->addr.type == BDADDR_LE_PUBLIC)
2853 addr_type = ADDR_LE_DEV_PUBLIC;
2854 else
2855 addr_type = ADDR_LE_DEV_RANDOM;
2856
2857 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002858 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002859 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002860
Ville Tervo30e76272011-02-22 16:10:53 -03002861 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002862 int status;
2863
2864 if (PTR_ERR(conn) == -EBUSY)
2865 status = MGMT_STATUS_BUSY;
2866 else
2867 status = MGMT_STATUS_CONNECT_FAILED;
2868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002869 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002870 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002871 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002872 goto unlock;
2873 }
2874
2875 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002876 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002877 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002878 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002879 goto unlock;
2880 }
2881
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002882 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002883 if (!cmd) {
2884 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002885 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002886 goto unlock;
2887 }
2888
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002889 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002890 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002891 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002892 conn->security_cfm_cb = pairing_complete_cb;
2893 conn->disconn_cfm_cb = pairing_complete_cb;
2894 } else {
2895 conn->connect_cfm_cb = le_pairing_complete_cb;
2896 conn->security_cfm_cb = le_pairing_complete_cb;
2897 conn->disconn_cfm_cb = le_pairing_complete_cb;
2898 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002899
Johan Hedberge9a416b2011-02-19 12:05:56 -03002900 conn->io_capability = cp->io_cap;
2901 cmd->user_data = conn;
2902
2903 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002904 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002905 pairing_complete(cmd, 0);
2906
2907 err = 0;
2908
2909unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002910 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002911 return err;
2912}
2913
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002914static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2915 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002916{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002917 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002918 struct pending_cmd *cmd;
2919 struct hci_conn *conn;
2920 int err;
2921
2922 BT_DBG("");
2923
Johan Hedberg28424702012-02-02 04:02:29 +02002924 hci_dev_lock(hdev);
2925
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002926 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002927 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002928 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002929 goto unlock;
2930 }
2931
Johan Hedberg28424702012-02-02 04:02:29 +02002932 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2933 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002934 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002935 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002936 goto unlock;
2937 }
2938
2939 conn = cmd->user_data;
2940
2941 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002942 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002943 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002944 goto unlock;
2945 }
2946
2947 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2948
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002949 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002950 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02002951unlock:
2952 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02002953 return err;
2954}
2955
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002956static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05002957 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002958 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03002959{
Johan Hedberga5c29682011-02-19 12:05:57 -03002960 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08002961 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002962 int err;
2963
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002964 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02002965
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002966 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002967 err = cmd_complete(sk, hdev->id, mgmt_op,
2968 MGMT_STATUS_NOT_POWERED, addr,
2969 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08002970 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002971 }
2972
Johan Hedberg1707c602013-03-15 17:07:15 -05002973 if (addr->type == BDADDR_BREDR)
2974 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02002975 else
Johan Hedberg1707c602013-03-15 17:07:15 -05002976 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08002977
Johan Hedberg272d90d2012-02-09 15:26:12 +02002978 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002979 err = cmd_complete(sk, hdev->id, mgmt_op,
2980 MGMT_STATUS_NOT_CONNECTED, addr,
2981 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02002982 goto done;
2983 }
2984
Johan Hedberg1707c602013-03-15 17:07:15 -05002985 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08002986 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08002987 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08002988
Brian Gix5fe57d92011-12-21 16:12:13 -08002989 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002990 err = cmd_complete(sk, hdev->id, mgmt_op,
2991 MGMT_STATUS_SUCCESS, addr,
2992 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08002993 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002994 err = cmd_complete(sk, hdev->id, mgmt_op,
2995 MGMT_STATUS_FAILED, addr,
2996 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08002997
Brian Gix47c15e22011-11-16 13:53:14 -08002998 goto done;
2999 }
3000
Johan Hedberg1707c602013-03-15 17:07:15 -05003001 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003002 if (!cmd) {
3003 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003004 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003005 }
3006
Brian Gix0df4c182011-11-16 13:53:13 -08003007 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003008 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3009 struct hci_cp_user_passkey_reply cp;
3010
Johan Hedberg1707c602013-03-15 17:07:15 -05003011 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003012 cp.passkey = passkey;
3013 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3014 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003015 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3016 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003017
Johan Hedberga664b5b2011-02-19 12:06:02 -03003018 if (err < 0)
3019 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003020
Brian Gix0df4c182011-11-16 13:53:13 -08003021done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003022 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003023 return err;
3024}
3025
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303026static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3027 void *data, u16 len)
3028{
3029 struct mgmt_cp_pin_code_neg_reply *cp = data;
3030
3031 BT_DBG("");
3032
Johan Hedberg1707c602013-03-15 17:07:15 -05003033 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303034 MGMT_OP_PIN_CODE_NEG_REPLY,
3035 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3036}
3037
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003038static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3039 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003040{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003041 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003042
3043 BT_DBG("");
3044
3045 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003046 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003047 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003048
Johan Hedberg1707c602013-03-15 17:07:15 -05003049 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003050 MGMT_OP_USER_CONFIRM_REPLY,
3051 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003052}
3053
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003054static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003055 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003056{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003057 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003058
3059 BT_DBG("");
3060
Johan Hedberg1707c602013-03-15 17:07:15 -05003061 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003062 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3063 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003064}
3065
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003066static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3067 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003068{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003069 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003070
3071 BT_DBG("");
3072
Johan Hedberg1707c602013-03-15 17:07:15 -05003073 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003074 MGMT_OP_USER_PASSKEY_REPLY,
3075 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003076}
3077
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003078static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003079 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003080{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003081 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003082
3083 BT_DBG("");
3084
Johan Hedberg1707c602013-03-15 17:07:15 -05003085 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003086 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3087 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003088}
3089
Johan Hedberg13928972013-03-15 17:07:00 -05003090static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003091{
Johan Hedberg13928972013-03-15 17:07:00 -05003092 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003093 struct hci_cp_write_local_name cp;
3094
Johan Hedberg13928972013-03-15 17:07:00 -05003095 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003096
Johan Hedberg890ea892013-03-15 17:06:52 -05003097 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003098}
3099
Johan Hedberg13928972013-03-15 17:07:00 -05003100static void set_name_complete(struct hci_dev *hdev, u8 status)
3101{
3102 struct mgmt_cp_set_local_name *cp;
3103 struct pending_cmd *cmd;
3104
3105 BT_DBG("status 0x%02x", status);
3106
3107 hci_dev_lock(hdev);
3108
3109 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3110 if (!cmd)
3111 goto unlock;
3112
3113 cp = cmd->param;
3114
3115 if (status)
3116 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3117 mgmt_status(status));
3118 else
3119 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3120 cp, sizeof(*cp));
3121
3122 mgmt_pending_remove(cmd);
3123
3124unlock:
3125 hci_dev_unlock(hdev);
3126}
3127
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003128static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003129 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003130{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003131 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003132 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003133 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003134 int err;
3135
3136 BT_DBG("");
3137
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003138 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003139
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003140 /* If the old values are the same as the new ones just return a
3141 * direct command complete event.
3142 */
3143 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3144 !memcmp(hdev->short_name, cp->short_name,
3145 sizeof(hdev->short_name))) {
3146 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3147 data, len);
3148 goto failed;
3149 }
3150
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003151 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003152
Johan Hedbergb5235a62012-02-21 14:32:24 +02003153 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003154 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003155
3156 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003157 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003158 if (err < 0)
3159 goto failed;
3160
3161 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003162 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003163
Johan Hedbergb5235a62012-02-21 14:32:24 +02003164 goto failed;
3165 }
3166
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003167 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003168 if (!cmd) {
3169 err = -ENOMEM;
3170 goto failed;
3171 }
3172
Johan Hedberg13928972013-03-15 17:07:00 -05003173 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3174
Johan Hedberg890ea892013-03-15 17:06:52 -05003175 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003176
3177 if (lmp_bredr_capable(hdev)) {
3178 update_name(&req);
3179 update_eir(&req);
3180 }
3181
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003182 /* The name is stored in the scan response data and so
3183 * no need to udpate the advertising data here.
3184 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003185 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003186 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003187
Johan Hedberg13928972013-03-15 17:07:00 -05003188 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003189 if (err < 0)
3190 mgmt_pending_remove(cmd);
3191
3192failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003193 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003194 return err;
3195}
3196
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003197static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003198 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003199{
Szymon Jancc35938b2011-03-22 13:12:21 +01003200 struct pending_cmd *cmd;
3201 int err;
3202
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003203 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003204
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003205 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003206
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003207 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003208 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003209 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003210 goto unlock;
3211 }
3212
Andre Guedes9a1a1992012-07-24 15:03:48 -03003213 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003214 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003215 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003216 goto unlock;
3217 }
3218
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003219 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003220 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003222 goto unlock;
3223 }
3224
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003225 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003226 if (!cmd) {
3227 err = -ENOMEM;
3228 goto unlock;
3229 }
3230
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003231 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3232 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3233 0, NULL);
3234 else
3235 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3236
Szymon Jancc35938b2011-03-22 13:12:21 +01003237 if (err < 0)
3238 mgmt_pending_remove(cmd);
3239
3240unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003241 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003242 return err;
3243}
3244
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003245static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003246 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003247{
Szymon Janc2763eda2011-03-22 13:12:22 +01003248 int err;
3249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003250 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003251
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003252 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003253
Marcel Holtmannec109112014-01-10 02:07:30 -08003254 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3255 struct mgmt_cp_add_remote_oob_data *cp = data;
3256 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003257
Marcel Holtmannec109112014-01-10 02:07:30 -08003258 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3259 cp->hash, cp->randomizer);
3260 if (err < 0)
3261 status = MGMT_STATUS_FAILED;
3262 else
3263 status = MGMT_STATUS_SUCCESS;
3264
3265 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3266 status, &cp->addr, sizeof(cp->addr));
3267 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3268 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3269 u8 status;
3270
3271 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3272 cp->hash192,
3273 cp->randomizer192,
3274 cp->hash256,
3275 cp->randomizer256);
3276 if (err < 0)
3277 status = MGMT_STATUS_FAILED;
3278 else
3279 status = MGMT_STATUS_SUCCESS;
3280
3281 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3282 status, &cp->addr, sizeof(cp->addr));
3283 } else {
3284 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3285 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3286 MGMT_STATUS_INVALID_PARAMS);
3287 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003288
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003289 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003290 return err;
3291}
3292
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003293static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003294 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003295{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003296 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003297 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003298 int err;
3299
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003300 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003301
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003302 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003303
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003304 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003305 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003306 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003307 else
Szymon Janca6785be2012-12-13 15:11:21 +01003308 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003309
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003310 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003311 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003312
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003313 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003314 return err;
3315}
3316
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003317static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3318{
3319 struct pending_cmd *cmd;
3320 u8 type;
3321 int err;
3322
3323 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3324
3325 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3326 if (!cmd)
3327 return -ENOENT;
3328
3329 type = hdev->discovery.type;
3330
3331 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3332 &type, sizeof(type));
3333 mgmt_pending_remove(cmd);
3334
3335 return err;
3336}
3337
Andre Guedes7c307722013-04-30 15:29:28 -03003338static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3339{
3340 BT_DBG("status %d", status);
3341
3342 if (status) {
3343 hci_dev_lock(hdev);
3344 mgmt_start_discovery_failed(hdev, status);
3345 hci_dev_unlock(hdev);
3346 return;
3347 }
3348
3349 hci_dev_lock(hdev);
3350 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3351 hci_dev_unlock(hdev);
3352
3353 switch (hdev->discovery.type) {
3354 case DISCOV_TYPE_LE:
3355 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003356 DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003357 break;
3358
3359 case DISCOV_TYPE_INTERLEAVED:
3360 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003361 DISCOV_INTERLEAVED_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003362 break;
3363
3364 case DISCOV_TYPE_BREDR:
3365 break;
3366
3367 default:
3368 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3369 }
3370}
3371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003372static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003373 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003374{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003375 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003376 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003377 struct hci_cp_le_set_scan_param param_cp;
3378 struct hci_cp_le_set_scan_enable enable_cp;
3379 struct hci_cp_inquiry inq_cp;
3380 struct hci_request req;
3381 /* General inquiry access code (GIAC) */
3382 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003383 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003384 int err;
3385
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003386 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003387
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003388 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003389
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003390 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003391 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003392 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003393 goto failed;
3394 }
3395
Andre Guedes642be6c2012-03-21 00:03:37 -03003396 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3397 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3398 MGMT_STATUS_BUSY);
3399 goto failed;
3400 }
3401
Johan Hedbergff9ef572012-01-04 14:23:45 +02003402 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003403 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003404 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003405 goto failed;
3406 }
3407
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003408 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003409 if (!cmd) {
3410 err = -ENOMEM;
3411 goto failed;
3412 }
3413
Andre Guedes4aab14e2012-02-17 20:39:36 -03003414 hdev->discovery.type = cp->type;
3415
Andre Guedes7c307722013-04-30 15:29:28 -03003416 hci_req_init(&req, hdev);
3417
Andre Guedes4aab14e2012-02-17 20:39:36 -03003418 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003419 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003420 status = mgmt_bredr_support(hdev);
3421 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003422 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003423 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003424 mgmt_pending_remove(cmd);
3425 goto failed;
3426 }
3427
Andre Guedes7c307722013-04-30 15:29:28 -03003428 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3429 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3430 MGMT_STATUS_BUSY);
3431 mgmt_pending_remove(cmd);
3432 goto failed;
3433 }
3434
3435 hci_inquiry_cache_flush(hdev);
3436
3437 memset(&inq_cp, 0, sizeof(inq_cp));
3438 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003439 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003440 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003441 break;
3442
3443 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003444 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003445 status = mgmt_le_support(hdev);
3446 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003447 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003448 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003449 mgmt_pending_remove(cmd);
3450 goto failed;
3451 }
3452
Andre Guedes7c307722013-04-30 15:29:28 -03003453 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003454 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003455 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3456 MGMT_STATUS_NOT_SUPPORTED);
3457 mgmt_pending_remove(cmd);
3458 goto failed;
3459 }
3460
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003461 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003462 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3463 MGMT_STATUS_REJECTED);
3464 mgmt_pending_remove(cmd);
3465 goto failed;
3466 }
3467
Andre Guedesc54c3862014-02-26 20:21:50 -03003468 /* If controller is scanning, it means the background scanning
3469 * is running. Thus, we should temporarily stop it in order to
3470 * set the discovery scanning parameters.
3471 */
3472 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3473 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003474
3475 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003476
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003477 /* All active scans will be done with either a resolvable
3478 * private address (when privacy feature has been enabled)
3479 * or unresolvable private address.
3480 */
3481 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003482 if (err < 0) {
3483 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3484 MGMT_STATUS_FAILED);
3485 mgmt_pending_remove(cmd);
3486 goto failed;
3487 }
3488
Andre Guedes7c307722013-04-30 15:29:28 -03003489 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003490 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3491 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003492 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003493 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3494 &param_cp);
3495
3496 memset(&enable_cp, 0, sizeof(enable_cp));
3497 enable_cp.enable = LE_SCAN_ENABLE;
3498 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3499 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3500 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003501 break;
3502
Andre Guedesf39799f2012-02-17 20:39:35 -03003503 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003504 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3505 MGMT_STATUS_INVALID_PARAMS);
3506 mgmt_pending_remove(cmd);
3507 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003508 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003509
Andre Guedes7c307722013-04-30 15:29:28 -03003510 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003511 if (err < 0)
3512 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003513 else
3514 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003515
3516failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003517 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003518 return err;
3519}
3520
Andre Guedes1183fdc2013-04-30 15:29:35 -03003521static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3522{
3523 struct pending_cmd *cmd;
3524 int err;
3525
3526 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3527 if (!cmd)
3528 return -ENOENT;
3529
3530 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3531 &hdev->discovery.type, sizeof(hdev->discovery.type));
3532 mgmt_pending_remove(cmd);
3533
3534 return err;
3535}
3536
Andre Guedes0e05bba2013-04-30 15:29:33 -03003537static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3538{
3539 BT_DBG("status %d", status);
3540
3541 hci_dev_lock(hdev);
3542
3543 if (status) {
3544 mgmt_stop_discovery_failed(hdev, status);
3545 goto unlock;
3546 }
3547
3548 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3549
3550unlock:
3551 hci_dev_unlock(hdev);
3552}
3553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003554static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003555 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003556{
Johan Hedbergd9306502012-02-20 23:25:18 +02003557 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003558 struct pending_cmd *cmd;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003559 struct hci_cp_remote_name_req_cancel cp;
3560 struct inquiry_entry *e;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003561 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003562 int err;
3563
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003564 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003565
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003566 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003567
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003568 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003569 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003570 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3571 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003572 goto unlock;
3573 }
3574
3575 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003576 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003577 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3578 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003579 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003580 }
3581
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003582 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003583 if (!cmd) {
3584 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003585 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003586 }
3587
Andre Guedes0e05bba2013-04-30 15:29:33 -03003588 hci_req_init(&req, hdev);
3589
Andre Guedese0d9727e2012-03-20 15:15:36 -03003590 switch (hdev->discovery.state) {
3591 case DISCOVERY_FINDING:
Andre Guedes0e05bba2013-04-30 15:29:33 -03003592 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3593 hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
3594 } else {
3595 cancel_delayed_work(&hdev->le_scan_disable);
3596
Andre Guedesb1efcc22014-02-26 20:21:40 -03003597 hci_req_add_le_scan_disable(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003598 }
Andre Guedesc9ecc482012-03-15 16:52:08 -03003599
Andre Guedese0d9727e2012-03-20 15:15:36 -03003600 break;
3601
3602 case DISCOVERY_RESOLVING:
3603 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003604 NAME_PENDING);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003605 if (!e) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003606 mgmt_pending_remove(cmd);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003607 err = cmd_complete(sk, hdev->id,
3608 MGMT_OP_STOP_DISCOVERY, 0,
3609 &mgmt_cp->type,
3610 sizeof(mgmt_cp->type));
3611 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3612 goto unlock;
3613 }
3614
3615 bacpy(&cp.bdaddr, &e->data.bdaddr);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003616 hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
3617 &cp);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003618
3619 break;
3620
3621 default:
3622 BT_DBG("unknown discovery state %u", hdev->discovery.state);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003623
3624 mgmt_pending_remove(cmd);
3625 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
3626 MGMT_STATUS_FAILED, &mgmt_cp->type,
3627 sizeof(mgmt_cp->type));
3628 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003629 }
3630
Andre Guedes0e05bba2013-04-30 15:29:33 -03003631 err = hci_req_run(&req, stop_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003632 if (err < 0)
3633 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003634 else
3635 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003636
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003637unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003638 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003639 return err;
3640}
3641
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003642static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003643 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003644{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003645 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003646 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003647 int err;
3648
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003649 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003650
Johan Hedberg561aafb2012-01-04 13:31:59 +02003651 hci_dev_lock(hdev);
3652
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003653 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003654 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3655 MGMT_STATUS_FAILED, &cp->addr,
3656 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003657 goto failed;
3658 }
3659
Johan Hedberga198e7b2012-02-17 14:27:06 +02003660 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003661 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003662 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3663 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3664 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003665 goto failed;
3666 }
3667
3668 if (cp->name_known) {
3669 e->name_state = NAME_KNOWN;
3670 list_del(&e->list);
3671 } else {
3672 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003673 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003674 }
3675
Johan Hedberge3846622013-01-09 15:29:33 +02003676 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3677 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003678
3679failed:
3680 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003681 return err;
3682}
3683
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003684static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003685 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003686{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003687 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003688 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003689 int err;
3690
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003691 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003692
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003693 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003694 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3695 MGMT_STATUS_INVALID_PARAMS,
3696 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003697
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003698 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003699
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003700 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003701 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003702 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003703 else
Szymon Janca6785be2012-12-13 15:11:21 +01003704 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003706 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003707 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003708
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003709 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003710
3711 return err;
3712}
3713
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003714static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003715 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003716{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003717 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003718 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003719 int err;
3720
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003721 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003722
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003723 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003724 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3725 MGMT_STATUS_INVALID_PARAMS,
3726 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003727
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003728 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003729
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003730 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003731 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003732 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003733 else
Szymon Janca6785be2012-12-13 15:11:21 +01003734 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003736 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003737 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003738
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003739 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003740
3741 return err;
3742}
3743
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003744static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3745 u16 len)
3746{
3747 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003748 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003749 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003750 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003751
3752 BT_DBG("%s", hdev->name);
3753
Szymon Jancc72d4b82012-03-16 16:02:57 +01003754 source = __le16_to_cpu(cp->source);
3755
3756 if (source > 0x0002)
3757 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3758 MGMT_STATUS_INVALID_PARAMS);
3759
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003760 hci_dev_lock(hdev);
3761
Szymon Jancc72d4b82012-03-16 16:02:57 +01003762 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003763 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3764 hdev->devid_product = __le16_to_cpu(cp->product);
3765 hdev->devid_version = __le16_to_cpu(cp->version);
3766
3767 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3768
Johan Hedberg890ea892013-03-15 17:06:52 -05003769 hci_req_init(&req, hdev);
3770 update_eir(&req);
3771 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003772
3773 hci_dev_unlock(hdev);
3774
3775 return err;
3776}
3777
Johan Hedberg4375f102013-09-25 13:26:10 +03003778static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3779{
3780 struct cmd_lookup match = { NULL, hdev };
3781
3782 if (status) {
3783 u8 mgmt_err = mgmt_status(status);
3784
3785 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3786 cmd_status_rsp, &mgmt_err);
3787 return;
3788 }
3789
3790 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3791 &match);
3792
3793 new_settings(hdev, match.sk);
3794
3795 if (match.sk)
3796 sock_put(match.sk);
3797}
3798
Marcel Holtmann21b51872013-10-10 09:47:53 -07003799static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3800 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003801{
3802 struct mgmt_mode *cp = data;
3803 struct pending_cmd *cmd;
3804 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003805 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003806 int err;
3807
3808 BT_DBG("request for %s", hdev->name);
3809
Johan Hedberge6fe7982013-10-02 15:45:22 +03003810 status = mgmt_le_support(hdev);
3811 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003812 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003813 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003814
3815 if (cp->val != 0x00 && cp->val != 0x01)
3816 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3817 MGMT_STATUS_INVALID_PARAMS);
3818
3819 hci_dev_lock(hdev);
3820
3821 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003822 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003823
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003824 /* The following conditions are ones which mean that we should
3825 * not do any HCI communication but directly send a mgmt
3826 * response to user space (after toggling the flag if
3827 * necessary).
3828 */
3829 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003830 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003831 bool changed = false;
3832
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003833 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3834 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003835 changed = true;
3836 }
3837
3838 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3839 if (err < 0)
3840 goto unlock;
3841
3842 if (changed)
3843 err = new_settings(hdev, sk);
3844
3845 goto unlock;
3846 }
3847
3848 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3849 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3850 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3851 MGMT_STATUS_BUSY);
3852 goto unlock;
3853 }
3854
3855 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3856 if (!cmd) {
3857 err = -ENOMEM;
3858 goto unlock;
3859 }
3860
3861 hci_req_init(&req, hdev);
3862
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003863 if (val)
3864 enable_advertising(&req);
3865 else
3866 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003867
3868 err = hci_req_run(&req, set_advertising_complete);
3869 if (err < 0)
3870 mgmt_pending_remove(cmd);
3871
3872unlock:
3873 hci_dev_unlock(hdev);
3874 return err;
3875}
3876
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003877static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3878 void *data, u16 len)
3879{
3880 struct mgmt_cp_set_static_address *cp = data;
3881 int err;
3882
3883 BT_DBG("%s", hdev->name);
3884
Marcel Holtmann62af4442013-10-02 22:10:32 -07003885 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003886 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003887 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003888
3889 if (hdev_is_powered(hdev))
3890 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3891 MGMT_STATUS_REJECTED);
3892
3893 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3894 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3895 return cmd_status(sk, hdev->id,
3896 MGMT_OP_SET_STATIC_ADDRESS,
3897 MGMT_STATUS_INVALID_PARAMS);
3898
3899 /* Two most significant bits shall be set */
3900 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3901 return cmd_status(sk, hdev->id,
3902 MGMT_OP_SET_STATIC_ADDRESS,
3903 MGMT_STATUS_INVALID_PARAMS);
3904 }
3905
3906 hci_dev_lock(hdev);
3907
3908 bacpy(&hdev->static_addr, &cp->bdaddr);
3909
3910 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3911
3912 hci_dev_unlock(hdev);
3913
3914 return err;
3915}
3916
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003917static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3918 void *data, u16 len)
3919{
3920 struct mgmt_cp_set_scan_params *cp = data;
3921 __u16 interval, window;
3922 int err;
3923
3924 BT_DBG("%s", hdev->name);
3925
3926 if (!lmp_le_capable(hdev))
3927 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3928 MGMT_STATUS_NOT_SUPPORTED);
3929
3930 interval = __le16_to_cpu(cp->interval);
3931
3932 if (interval < 0x0004 || interval > 0x4000)
3933 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3934 MGMT_STATUS_INVALID_PARAMS);
3935
3936 window = __le16_to_cpu(cp->window);
3937
3938 if (window < 0x0004 || window > 0x4000)
3939 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3940 MGMT_STATUS_INVALID_PARAMS);
3941
Marcel Holtmann899e1072013-10-14 09:55:32 -07003942 if (window > interval)
3943 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3944 MGMT_STATUS_INVALID_PARAMS);
3945
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003946 hci_dev_lock(hdev);
3947
3948 hdev->le_scan_interval = interval;
3949 hdev->le_scan_window = window;
3950
3951 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3952
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003953 /* If background scan is running, restart it so new parameters are
3954 * loaded.
3955 */
3956 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
3957 hdev->discovery.state == DISCOVERY_STOPPED) {
3958 struct hci_request req;
3959
3960 hci_req_init(&req, hdev);
3961
3962 hci_req_add_le_scan_disable(&req);
3963 hci_req_add_le_passive_scan(&req);
3964
3965 hci_req_run(&req, NULL);
3966 }
3967
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003968 hci_dev_unlock(hdev);
3969
3970 return err;
3971}
3972
Johan Hedberg33e38b32013-03-15 17:07:05 -05003973static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3974{
3975 struct pending_cmd *cmd;
3976
3977 BT_DBG("status 0x%02x", status);
3978
3979 hci_dev_lock(hdev);
3980
3981 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3982 if (!cmd)
3983 goto unlock;
3984
3985 if (status) {
3986 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3987 mgmt_status(status));
3988 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05003989 struct mgmt_mode *cp = cmd->param;
3990
3991 if (cp->val)
3992 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
3993 else
3994 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
3995
Johan Hedberg33e38b32013-03-15 17:07:05 -05003996 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3997 new_settings(hdev, cmd->sk);
3998 }
3999
4000 mgmt_pending_remove(cmd);
4001
4002unlock:
4003 hci_dev_unlock(hdev);
4004}
4005
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004006static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004007 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004008{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004009 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004010 struct pending_cmd *cmd;
4011 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004012 int err;
4013
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004014 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004015
Johan Hedberg56f87902013-10-02 13:43:13 +03004016 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4017 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004018 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4019 MGMT_STATUS_NOT_SUPPORTED);
4020
Johan Hedberga7e80f22013-01-09 16:05:19 +02004021 if (cp->val != 0x00 && cp->val != 0x01)
4022 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4023 MGMT_STATUS_INVALID_PARAMS);
4024
Johan Hedberg5400c042012-02-21 16:40:33 +02004025 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004026 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004027 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004028
4029 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004030 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004031 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004032
4033 hci_dev_lock(hdev);
4034
Johan Hedberg05cbf292013-03-15 17:07:07 -05004035 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4037 MGMT_STATUS_BUSY);
4038 goto unlock;
4039 }
4040
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004041 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4042 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4043 hdev);
4044 goto unlock;
4045 }
4046
Johan Hedberg33e38b32013-03-15 17:07:05 -05004047 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4048 data, len);
4049 if (!cmd) {
4050 err = -ENOMEM;
4051 goto unlock;
4052 }
4053
4054 hci_req_init(&req, hdev);
4055
Johan Hedberg406d7802013-03-15 17:07:09 -05004056 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004057
4058 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004059 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004060 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004061 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004062 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004063 }
4064
Johan Hedberg33e38b32013-03-15 17:07:05 -05004065unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004066 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004067
Antti Julkuf6422ec2011-06-22 13:11:56 +03004068 return err;
4069}
4070
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004071static void set_bredr_scan(struct hci_request *req)
4072{
4073 struct hci_dev *hdev = req->hdev;
4074 u8 scan = 0;
4075
4076 /* Ensure that fast connectable is disabled. This function will
4077 * not do anything if the page scan parameters are already what
4078 * they should be.
4079 */
4080 write_fast_connectable(req, false);
4081
4082 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4083 scan |= SCAN_PAGE;
4084 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4085 scan |= SCAN_INQUIRY;
4086
4087 if (scan)
4088 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4089}
4090
Johan Hedberg0663ca22013-10-02 13:43:14 +03004091static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4092{
4093 struct pending_cmd *cmd;
4094
4095 BT_DBG("status 0x%02x", status);
4096
4097 hci_dev_lock(hdev);
4098
4099 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4100 if (!cmd)
4101 goto unlock;
4102
4103 if (status) {
4104 u8 mgmt_err = mgmt_status(status);
4105
4106 /* We need to restore the flag if related HCI commands
4107 * failed.
4108 */
4109 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4110
4111 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4112 } else {
4113 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4114 new_settings(hdev, cmd->sk);
4115 }
4116
4117 mgmt_pending_remove(cmd);
4118
4119unlock:
4120 hci_dev_unlock(hdev);
4121}
4122
4123static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4124{
4125 struct mgmt_mode *cp = data;
4126 struct pending_cmd *cmd;
4127 struct hci_request req;
4128 int err;
4129
4130 BT_DBG("request for %s", hdev->name);
4131
4132 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4133 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4134 MGMT_STATUS_NOT_SUPPORTED);
4135
4136 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4137 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4138 MGMT_STATUS_REJECTED);
4139
4140 if (cp->val != 0x00 && cp->val != 0x01)
4141 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4142 MGMT_STATUS_INVALID_PARAMS);
4143
4144 hci_dev_lock(hdev);
4145
4146 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4147 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4148 goto unlock;
4149 }
4150
4151 if (!hdev_is_powered(hdev)) {
4152 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004153 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4154 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4155 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4156 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4157 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4158 }
4159
4160 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4161
4162 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4163 if (err < 0)
4164 goto unlock;
4165
4166 err = new_settings(hdev, sk);
4167 goto unlock;
4168 }
4169
4170 /* Reject disabling when powered on */
4171 if (!cp->val) {
4172 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4173 MGMT_STATUS_REJECTED);
4174 goto unlock;
4175 }
4176
4177 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4179 MGMT_STATUS_BUSY);
4180 goto unlock;
4181 }
4182
4183 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4184 if (!cmd) {
4185 err = -ENOMEM;
4186 goto unlock;
4187 }
4188
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004189 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004190 * generates the correct flags.
4191 */
4192 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4193
4194 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004195
4196 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4197 set_bredr_scan(&req);
4198
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004199 /* Since only the advertising data flags will change, there
4200 * is no need to update the scan response data.
4201 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004202 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004203
Johan Hedberg0663ca22013-10-02 13:43:14 +03004204 err = hci_req_run(&req, set_bredr_complete);
4205 if (err < 0)
4206 mgmt_pending_remove(cmd);
4207
4208unlock:
4209 hci_dev_unlock(hdev);
4210 return err;
4211}
4212
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004213static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4214 void *data, u16 len)
4215{
4216 struct mgmt_mode *cp = data;
4217 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004218 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004219 int err;
4220
4221 BT_DBG("request for %s", hdev->name);
4222
4223 status = mgmt_bredr_support(hdev);
4224 if (status)
4225 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4226 status);
4227
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004228 if (!lmp_sc_capable(hdev) &&
4229 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004230 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4231 MGMT_STATUS_NOT_SUPPORTED);
4232
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004233 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004234 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4235 MGMT_STATUS_INVALID_PARAMS);
4236
4237 hci_dev_lock(hdev);
4238
4239 if (!hdev_is_powered(hdev)) {
4240 bool changed;
4241
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004242 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004243 changed = !test_and_set_bit(HCI_SC_ENABLED,
4244 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004245 if (cp->val == 0x02)
4246 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4247 else
4248 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4249 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004250 changed = test_and_clear_bit(HCI_SC_ENABLED,
4251 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004252 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4253 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004254
4255 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4256 if (err < 0)
4257 goto failed;
4258
4259 if (changed)
4260 err = new_settings(hdev, sk);
4261
4262 goto failed;
4263 }
4264
4265 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4266 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4267 MGMT_STATUS_BUSY);
4268 goto failed;
4269 }
4270
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004271 val = !!cp->val;
4272
4273 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4274 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004275 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4276 goto failed;
4277 }
4278
4279 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4280 if (!cmd) {
4281 err = -ENOMEM;
4282 goto failed;
4283 }
4284
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004285 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004286 if (err < 0) {
4287 mgmt_pending_remove(cmd);
4288 goto failed;
4289 }
4290
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004291 if (cp->val == 0x02)
4292 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4293 else
4294 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4295
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004296failed:
4297 hci_dev_unlock(hdev);
4298 return err;
4299}
4300
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004301static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4302 void *data, u16 len)
4303{
4304 struct mgmt_mode *cp = data;
4305 bool changed;
4306 int err;
4307
4308 BT_DBG("request for %s", hdev->name);
4309
4310 if (cp->val != 0x00 && cp->val != 0x01)
4311 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4312 MGMT_STATUS_INVALID_PARAMS);
4313
4314 hci_dev_lock(hdev);
4315
4316 if (cp->val)
4317 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4318 else
4319 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4320
4321 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4322 if (err < 0)
4323 goto unlock;
4324
4325 if (changed)
4326 err = new_settings(hdev, sk);
4327
4328unlock:
4329 hci_dev_unlock(hdev);
4330 return err;
4331}
4332
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004333static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4334 u16 len)
4335{
4336 struct mgmt_cp_set_privacy *cp = cp_data;
4337 bool changed;
4338 int err;
4339
4340 BT_DBG("request for %s", hdev->name);
4341
4342 if (!lmp_le_capable(hdev))
4343 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4344 MGMT_STATUS_NOT_SUPPORTED);
4345
4346 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4347 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4348 MGMT_STATUS_INVALID_PARAMS);
4349
4350 if (hdev_is_powered(hdev))
4351 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4352 MGMT_STATUS_REJECTED);
4353
4354 hci_dev_lock(hdev);
4355
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004356 /* If user space supports this command it is also expected to
4357 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4358 */
4359 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4360
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004361 if (cp->privacy) {
4362 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4363 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4364 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4365 } else {
4366 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4367 memset(hdev->irk, 0, sizeof(hdev->irk));
4368 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4369 }
4370
4371 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4372 if (err < 0)
4373 goto unlock;
4374
4375 if (changed)
4376 err = new_settings(hdev, sk);
4377
4378unlock:
4379 hci_dev_unlock(hdev);
4380 return err;
4381}
4382
Johan Hedberg41edf162014-02-18 10:19:35 +02004383static bool irk_is_valid(struct mgmt_irk_info *irk)
4384{
4385 switch (irk->addr.type) {
4386 case BDADDR_LE_PUBLIC:
4387 return true;
4388
4389 case BDADDR_LE_RANDOM:
4390 /* Two most significant bits shall be set */
4391 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4392 return false;
4393 return true;
4394 }
4395
4396 return false;
4397}
4398
4399static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4400 u16 len)
4401{
4402 struct mgmt_cp_load_irks *cp = cp_data;
4403 u16 irk_count, expected_len;
4404 int i, err;
4405
4406 BT_DBG("request for %s", hdev->name);
4407
4408 if (!lmp_le_capable(hdev))
4409 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4410 MGMT_STATUS_NOT_SUPPORTED);
4411
4412 irk_count = __le16_to_cpu(cp->irk_count);
4413
4414 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4415 if (expected_len != len) {
4416 BT_ERR("load_irks: expected %u bytes, got %u bytes",
4417 len, expected_len);
4418 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4419 MGMT_STATUS_INVALID_PARAMS);
4420 }
4421
4422 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4423
4424 for (i = 0; i < irk_count; i++) {
4425 struct mgmt_irk_info *key = &cp->irks[i];
4426
4427 if (!irk_is_valid(key))
4428 return cmd_status(sk, hdev->id,
4429 MGMT_OP_LOAD_IRKS,
4430 MGMT_STATUS_INVALID_PARAMS);
4431 }
4432
4433 hci_dev_lock(hdev);
4434
4435 hci_smp_irks_clear(hdev);
4436
4437 for (i = 0; i < irk_count; i++) {
4438 struct mgmt_irk_info *irk = &cp->irks[i];
4439 u8 addr_type;
4440
4441 if (irk->addr.type == BDADDR_LE_PUBLIC)
4442 addr_type = ADDR_LE_DEV_PUBLIC;
4443 else
4444 addr_type = ADDR_LE_DEV_RANDOM;
4445
4446 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4447 BDADDR_ANY);
4448 }
4449
4450 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4451
4452 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4453
4454 hci_dev_unlock(hdev);
4455
4456 return err;
4457}
4458
Johan Hedberg3f706b72013-01-20 14:27:16 +02004459static bool ltk_is_valid(struct mgmt_ltk_info *key)
4460{
4461 if (key->master != 0x00 && key->master != 0x01)
4462 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004463
4464 switch (key->addr.type) {
4465 case BDADDR_LE_PUBLIC:
4466 return true;
4467
4468 case BDADDR_LE_RANDOM:
4469 /* Two most significant bits shall be set */
4470 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4471 return false;
4472 return true;
4473 }
4474
4475 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004476}
4477
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004478static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004479 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004480{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004481 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4482 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004483 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004484
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004485 BT_DBG("request for %s", hdev->name);
4486
4487 if (!lmp_le_capable(hdev))
4488 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4489 MGMT_STATUS_NOT_SUPPORTED);
4490
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004491 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004492
4493 expected_len = sizeof(*cp) + key_count *
4494 sizeof(struct mgmt_ltk_info);
4495 if (expected_len != len) {
4496 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004497 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004498 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004499 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004500 }
4501
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004502 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004503
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004504 for (i = 0; i < key_count; i++) {
4505 struct mgmt_ltk_info *key = &cp->keys[i];
4506
Johan Hedberg3f706b72013-01-20 14:27:16 +02004507 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004508 return cmd_status(sk, hdev->id,
4509 MGMT_OP_LOAD_LONG_TERM_KEYS,
4510 MGMT_STATUS_INVALID_PARAMS);
4511 }
4512
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004513 hci_dev_lock(hdev);
4514
4515 hci_smp_ltks_clear(hdev);
4516
4517 for (i = 0; i < key_count; i++) {
4518 struct mgmt_ltk_info *key = &cp->keys[i];
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004519 u8 type, addr_type;
4520
4521 if (key->addr.type == BDADDR_LE_PUBLIC)
4522 addr_type = ADDR_LE_DEV_PUBLIC;
4523 else
4524 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004525
4526 if (key->master)
4527 type = HCI_SMP_LTK;
4528 else
4529 type = HCI_SMP_LTK_SLAVE;
4530
Johan Hedberg35d70272014-02-19 14:57:47 +02004531 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
4532 key->type, key->val, key->enc_size, key->ediv,
4533 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004534 }
4535
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004536 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4537 NULL, 0);
4538
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004539 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004540
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004541 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004542}
4543
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004544static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004545 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4546 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004547 bool var_len;
4548 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004549} mgmt_handlers[] = {
4550 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004551 { read_version, false, MGMT_READ_VERSION_SIZE },
4552 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4553 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4554 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4555 { set_powered, false, MGMT_SETTING_SIZE },
4556 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4557 { set_connectable, false, MGMT_SETTING_SIZE },
4558 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4559 { set_pairable, false, MGMT_SETTING_SIZE },
4560 { set_link_security, false, MGMT_SETTING_SIZE },
4561 { set_ssp, false, MGMT_SETTING_SIZE },
4562 { set_hs, false, MGMT_SETTING_SIZE },
4563 { set_le, false, MGMT_SETTING_SIZE },
4564 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4565 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4566 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4567 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4568 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4569 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4570 { disconnect, false, MGMT_DISCONNECT_SIZE },
4571 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4572 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4573 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4574 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4575 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4576 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4577 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4578 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4579 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4580 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4581 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4582 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004583 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004584 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4585 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4586 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4587 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4588 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4589 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004590 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004591 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004592 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004593 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004594 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004595 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004596 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004597 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004598 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004599};
4600
4601
Johan Hedberg03811012010-12-08 00:21:06 +02004602int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4603{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004604 void *buf;
4605 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004606 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004607 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004608 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004609 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004610 int err;
4611
4612 BT_DBG("got %zu bytes", msglen);
4613
4614 if (msglen < sizeof(*hdr))
4615 return -EINVAL;
4616
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004617 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004618 if (!buf)
4619 return -ENOMEM;
4620
4621 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4622 err = -EFAULT;
4623 goto done;
4624 }
4625
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004626 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004627 opcode = __le16_to_cpu(hdr->opcode);
4628 index = __le16_to_cpu(hdr->index);
4629 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004630
4631 if (len != msglen - sizeof(*hdr)) {
4632 err = -EINVAL;
4633 goto done;
4634 }
4635
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004636 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004637 hdev = hci_dev_get(index);
4638 if (!hdev) {
4639 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004640 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004641 goto done;
4642 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004643
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004644 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4645 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004646 err = cmd_status(sk, index, opcode,
4647 MGMT_STATUS_INVALID_INDEX);
4648 goto done;
4649 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004650 }
4651
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004652 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004653 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004654 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004655 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004656 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004657 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004658 }
4659
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004660 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004661 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004662 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004663 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004664 goto done;
4665 }
4666
Johan Hedbergbe22b542012-03-01 22:24:41 +02004667 handler = &mgmt_handlers[opcode];
4668
4669 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004670 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004671 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004672 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004673 goto done;
4674 }
4675
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004676 if (hdev)
4677 mgmt_init_hdev(sk, hdev);
4678
4679 cp = buf + sizeof(*hdr);
4680
Johan Hedbergbe22b542012-03-01 22:24:41 +02004681 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004682 if (err < 0)
4683 goto done;
4684
Johan Hedberg03811012010-12-08 00:21:06 +02004685 err = msglen;
4686
4687done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004688 if (hdev)
4689 hci_dev_put(hdev);
4690
Johan Hedberg03811012010-12-08 00:21:06 +02004691 kfree(buf);
4692 return err;
4693}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004694
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004695void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004696{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004697 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004698 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004699
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004700 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004701}
4702
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004703void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004704{
Johan Hedberg5f159032012-03-02 03:13:19 +02004705 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004706
Marcel Holtmann1514b892013-10-06 08:25:01 -07004707 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004708 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004709
Johan Hedberg744cf192011-11-08 20:40:14 +02004710 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004711
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004712 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004713}
4714
Andre Guedes6046dc32014-02-26 20:21:51 -03004715/* This function requires the caller holds hdev->lock */
4716static void restart_le_auto_conns(struct hci_dev *hdev)
4717{
4718 struct hci_conn_params *p;
4719
4720 list_for_each_entry(p, &hdev->le_conn_params, list) {
4721 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4722 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4723 }
4724}
4725
Johan Hedberg229ab392013-03-15 17:06:53 -05004726static void powered_complete(struct hci_dev *hdev, u8 status)
4727{
4728 struct cmd_lookup match = { NULL, hdev };
4729
4730 BT_DBG("status 0x%02x", status);
4731
4732 hci_dev_lock(hdev);
4733
Andre Guedes6046dc32014-02-26 20:21:51 -03004734 restart_le_auto_conns(hdev);
4735
Johan Hedberg229ab392013-03-15 17:06:53 -05004736 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4737
4738 new_settings(hdev, match.sk);
4739
4740 hci_dev_unlock(hdev);
4741
4742 if (match.sk)
4743 sock_put(match.sk);
4744}
4745
Johan Hedberg70da6242013-03-15 17:06:51 -05004746static int powered_update_hci(struct hci_dev *hdev)
4747{
Johan Hedberg890ea892013-03-15 17:06:52 -05004748 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004749 u8 link_sec;
4750
Johan Hedberg890ea892013-03-15 17:06:52 -05004751 hci_req_init(&req, hdev);
4752
Johan Hedberg70da6242013-03-15 17:06:51 -05004753 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4754 !lmp_host_ssp_capable(hdev)) {
4755 u8 ssp = 1;
4756
Johan Hedberg890ea892013-03-15 17:06:52 -05004757 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004758 }
4759
Johan Hedbergc73eee92013-04-19 18:35:21 +03004760 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4761 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05004762 struct hci_cp_write_le_host_supported cp;
4763
4764 cp.le = 1;
4765 cp.simul = lmp_le_br_capable(hdev);
4766
4767 /* Check first if we already have the right
4768 * host state (host features set)
4769 */
4770 if (cp.le != lmp_host_le_capable(hdev) ||
4771 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05004772 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
4773 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004774 }
4775
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004776 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004777 /* Make sure the controller has a good default for
4778 * advertising data. This also applies to the case
4779 * where BR/EDR was toggled during the AUTO_OFF phase.
4780 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004781 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004782 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004783 update_scan_rsp_data(&req);
4784 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004785
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004786 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
4787 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03004788 }
4789
Johan Hedberg70da6242013-03-15 17:06:51 -05004790 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4791 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05004792 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
4793 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05004794
4795 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03004796 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
4797 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004798 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05004799 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004800 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05004801 }
4802
Johan Hedberg229ab392013-03-15 17:06:53 -05004803 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05004804}
4805
Johan Hedberg744cf192011-11-08 20:40:14 +02004806int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02004807{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02004808 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05004809 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
4810 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004811 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004812
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004813 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
4814 return 0;
4815
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004816 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05004817 if (powered_update_hci(hdev) == 0)
4818 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02004819
Johan Hedberg229ab392013-03-15 17:06:53 -05004820 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
4821 &match);
4822 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004823 }
4824
Johan Hedberg229ab392013-03-15 17:06:53 -05004825 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4826 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
4827
4828 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
4829 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
4830 zero_cod, sizeof(zero_cod), NULL);
4831
4832new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004833 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004834
4835 if (match.sk)
4836 sock_put(match.sk);
4837
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004838 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004839}
Johan Hedberg73f22f62010-12-29 16:00:25 +02004840
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004841void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03004842{
4843 struct pending_cmd *cmd;
4844 u8 status;
4845
4846 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
4847 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004848 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03004849
4850 if (err == -ERFKILL)
4851 status = MGMT_STATUS_RFKILLED;
4852 else
4853 status = MGMT_STATUS_FAILED;
4854
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004855 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004856
4857 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004858}
4859
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004860void mgmt_discoverable_timeout(struct hci_dev *hdev)
4861{
4862 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004863
4864 hci_dev_lock(hdev);
4865
4866 /* When discoverable timeout triggers, then just make sure
4867 * the limited discoverable flag is cleared. Even in the case
4868 * of a timeout triggered from general discoverable, it is
4869 * safe to unconditionally clear the flag.
4870 */
4871 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004872 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004873
4874 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03004875 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4876 u8 scan = SCAN_PAGE;
4877 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
4878 sizeof(scan), &scan);
4879 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004880 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004881 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004882 hci_req_run(&req, NULL);
4883
4884 hdev->discov_timeout = 0;
4885
Johan Hedberg9a43e252013-10-20 19:00:07 +03004886 new_settings(hdev, NULL);
4887
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004888 hci_dev_unlock(hdev);
4889}
4890
Marcel Holtmann86a75642013-10-15 06:33:54 -07004891void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02004892{
Marcel Holtmann86a75642013-10-15 06:33:54 -07004893 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02004894
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004895 /* Nothing needed here if there's a pending command since that
4896 * commands request completion callback takes care of everything
4897 * necessary.
4898 */
4899 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07004900 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004901
Johan Hedbergbd107992014-02-24 14:52:19 +02004902 /* Powering off may clear the scan mode - don't let that interfere */
4903 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4904 return;
4905
Johan Hedberg9a43e252013-10-20 19:00:07 +03004906 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07004907 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004908 } else {
4909 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07004910 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004911 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004912
Johan Hedberg9a43e252013-10-20 19:00:07 +03004913 if (changed) {
4914 struct hci_request req;
4915
4916 /* In case this change in discoverable was triggered by
4917 * a disabling of connectable there could be a need to
4918 * update the advertising flags.
4919 */
4920 hci_req_init(&req, hdev);
4921 update_adv_data(&req);
4922 hci_req_run(&req, NULL);
4923
Marcel Holtmann86a75642013-10-15 06:33:54 -07004924 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004925 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004926}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004927
Marcel Holtmanna3309162013-10-15 06:33:55 -07004928void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004929{
Marcel Holtmanna3309162013-10-15 06:33:55 -07004930 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004931
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004932 /* Nothing needed here if there's a pending command since that
4933 * commands request completion callback takes care of everything
4934 * necessary.
4935 */
4936 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07004937 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004938
Johan Hedbergce3f24c2014-02-24 14:52:20 +02004939 /* Powering off may clear the scan mode - don't let that interfere */
4940 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4941 return;
4942
Marcel Holtmanna3309162013-10-15 06:33:55 -07004943 if (connectable)
4944 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
4945 else
4946 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004947
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004948 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07004949 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004950}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004951
Johan Hedberg778b2352014-02-24 14:52:17 +02004952void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
4953{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02004954 /* Powering off may stop advertising - don't let that interfere */
4955 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4956 return;
4957
Johan Hedberg778b2352014-02-24 14:52:17 +02004958 if (advertising)
4959 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4960 else
4961 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4962}
4963
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07004964void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004965{
Johan Hedbergca69b792011-11-11 18:10:00 +02004966 u8 mgmt_err = mgmt_status(status);
4967
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004968 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02004969 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004970 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004971
4972 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02004973 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004974 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004975}
4976
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004977void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
4978 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004979{
Johan Hedberg86742e12011-11-07 23:13:38 +02004980 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004981
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004982 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004983
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004984 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02004985 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03004986 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004987 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03004988 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004989 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004990
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004991 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004992}
Johan Hedbergf7520542011-01-20 12:34:39 +02004993
Johan Hedbergba74b662014-02-19 14:57:45 +02004994void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004995{
4996 struct mgmt_ev_new_long_term_key ev;
4997
4998 memset(&ev, 0, sizeof(ev));
4999
Marcel Holtmann5192d302014-02-19 17:11:58 -08005000 /* Devices using resolvable or non-resolvable random addresses
5001 * without providing an indentity resolving key don't require
5002 * to store long term keys. Their addresses will change the
5003 * next time around.
5004 *
5005 * Only when a remote device provides an identity address
5006 * make sure the long term key is stored. If the remote
5007 * identity is known, the long term keys are internally
5008 * mapped to the identity address. So allow static random
5009 * and public addresses here.
5010 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005011 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5012 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5013 ev.store_hint = 0x00;
5014 else
5015 ev.store_hint = 0x01;
5016
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005017 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005018 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Marcel Holtmannd40f3ee2014-01-31 18:42:17 -08005019 ev.key.type = key->authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005020 ev.key.enc_size = key->enc_size;
5021 ev.key.ediv = key->ediv;
5022
5023 if (key->type == HCI_SMP_LTK)
5024 ev.key.master = 1;
5025
5026 memcpy(ev.key.rand, key->rand, sizeof(key->rand));
5027 memcpy(ev.key.val, key->val, sizeof(key->val));
5028
Marcel Holtmann083368f2013-10-15 14:26:29 -07005029 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005030}
5031
Johan Hedberg95fbac82014-02-19 15:18:31 +02005032void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5033{
5034 struct mgmt_ev_new_irk ev;
5035
5036 memset(&ev, 0, sizeof(ev));
5037
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005038 /* For identity resolving keys from devices that are already
5039 * using a public address or static random address, do not
5040 * ask for storing this key. The identity resolving key really
5041 * is only mandatory for devices using resovlable random
5042 * addresses.
5043 *
5044 * Storing all identity resolving keys has the downside that
5045 * they will be also loaded on next boot of they system. More
5046 * identity resolving keys, means more time during scanning is
5047 * needed to actually resolve these addresses.
5048 */
5049 if (bacmp(&irk->rpa, BDADDR_ANY))
5050 ev.store_hint = 0x01;
5051 else
5052 ev.store_hint = 0x00;
5053
Johan Hedberg95fbac82014-02-19 15:18:31 +02005054 bacpy(&ev.rpa, &irk->rpa);
5055 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5056 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5057 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5058
5059 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5060}
5061
Marcel Holtmann94933992013-10-15 10:26:39 -07005062static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5063 u8 data_len)
5064{
5065 eir[eir_len++] = sizeof(type) + data_len;
5066 eir[eir_len++] = type;
5067 memcpy(&eir[eir_len], data, data_len);
5068 eir_len += data_len;
5069
5070 return eir_len;
5071}
5072
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005073void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5074 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5075 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005076{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005077 char buf[512];
5078 struct mgmt_ev_device_connected *ev = (void *) buf;
5079 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005080
Johan Hedbergb644ba32012-01-17 21:48:47 +02005081 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005082 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005083
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005084 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005085
Johan Hedbergb644ba32012-01-17 21:48:47 +02005086 if (name_len > 0)
5087 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005088 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005089
5090 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005091 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005092 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005093
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005094 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005095
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005096 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5097 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005098}
5099
Johan Hedberg8962ee72011-01-20 12:40:27 +02005100static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5101{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005102 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005103 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005104 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005105
Johan Hedberg88c3df12012-02-09 14:27:38 +02005106 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5107 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005108
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005109 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005110 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005111
5112 *sk = cmd->sk;
5113 sock_hold(*sk);
5114
Johan Hedberga664b5b2011-02-19 12:06:02 -03005115 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005116}
5117
Johan Hedberg124f6e32012-02-09 13:50:12 +02005118static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005119{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005120 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005121 struct mgmt_cp_unpair_device *cp = cmd->param;
5122 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005123
5124 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005125 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5126 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005127
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005128 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5129
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005130 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005131
5132 mgmt_pending_remove(cmd);
5133}
5134
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005135void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005136 u8 link_type, u8 addr_type, u8 reason,
5137 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005138{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005139 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005140 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005141 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005142
Johan Hedberg8b064a32014-02-24 14:52:22 +02005143 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5144 if (power_off) {
5145 struct mgmt_mode *cp = power_off->param;
5146
5147 /* The connection is still in hci_conn_hash so test for 1
5148 * instead of 0 to know if this is the last one.
5149 */
5150 if (!cp->val && hci_conn_count(hdev) == 1)
5151 queue_work(hdev->req_workqueue, &hdev->power_off.work);
5152 }
5153
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005154 if (!mgmt_connected)
5155 return;
5156
Andre Guedes57eb7762013-10-30 19:01:41 -03005157 if (link_type != ACL_LINK && link_type != LE_LINK)
5158 return;
5159
Johan Hedberg744cf192011-11-08 20:40:14 +02005160 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005161
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005162 bacpy(&ev.addr.bdaddr, bdaddr);
5163 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5164 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005165
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005166 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005167
5168 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005169 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005170
Johan Hedberg124f6e32012-02-09 13:50:12 +02005171 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005172 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005173}
5174
Marcel Holtmann78929242013-10-06 23:55:47 -07005175void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5176 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005177{
Andre Guedes3655bba2013-10-30 19:01:40 -03005178 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5179 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005180 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005181 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005182
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005183 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5184 hdev);
5185
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005186 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005187 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005188 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005189
Andre Guedes3655bba2013-10-30 19:01:40 -03005190 cp = cmd->param;
5191
5192 if (bacmp(bdaddr, &cp->addr.bdaddr))
5193 return;
5194
5195 if (cp->addr.type != bdaddr_type)
5196 return;
5197
Johan Hedberg88c3df12012-02-09 14:27:38 +02005198 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005199 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005200
Marcel Holtmann78929242013-10-06 23:55:47 -07005201 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5202 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005203
Johan Hedberga664b5b2011-02-19 12:06:02 -03005204 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005205}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005206
Marcel Holtmann445608d2013-10-06 23:55:48 -07005207void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5208 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005209{
5210 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005211 struct pending_cmd *power_off;
5212
5213 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5214 if (power_off) {
5215 struct mgmt_mode *cp = power_off->param;
5216
5217 /* The connection is still in hci_conn_hash so test for 1
5218 * instead of 0 to know if this is the last one.
5219 */
5220 if (!cp->val && hci_conn_count(hdev) == 1)
5221 queue_work(hdev->req_workqueue, &hdev->power_off.work);
5222 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005223
Johan Hedberg4c659c32011-11-07 23:13:39 +02005224 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005225 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005226 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005227
Marcel Holtmann445608d2013-10-06 23:55:48 -07005228 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005229}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005230
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005231void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005232{
5233 struct mgmt_ev_pin_code_request ev;
5234
Johan Hedbergd8457692012-02-17 14:24:57 +02005235 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005236 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005237 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005238
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005239 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005240}
5241
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005242void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5243 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005244{
5245 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005246 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005247
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005248 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005249 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005250 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005251
Johan Hedbergd8457692012-02-17 14:24:57 +02005252 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005253 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005254
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005255 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5256 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005257
Johan Hedberga664b5b2011-02-19 12:06:02 -03005258 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005259}
5260
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005261void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5262 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005263{
5264 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005265 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005266
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005267 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005268 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005269 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005270
Johan Hedbergd8457692012-02-17 14:24:57 +02005271 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005272 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005273
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005274 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5275 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005276
Johan Hedberga664b5b2011-02-19 12:06:02 -03005277 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005278}
Johan Hedberga5c29682011-02-19 12:05:57 -03005279
Johan Hedberg744cf192011-11-08 20:40:14 +02005280int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005281 u8 link_type, u8 addr_type, __le32 value,
5282 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005283{
5284 struct mgmt_ev_user_confirm_request ev;
5285
Johan Hedberg744cf192011-11-08 20:40:14 +02005286 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005287
Johan Hedberg272d90d2012-02-09 15:26:12 +02005288 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005289 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005290 ev.confirm_hint = confirm_hint;
Andrei Emeltchenko78e8098e2012-03-09 13:00:50 +02005291 ev.value = value;
Johan Hedberga5c29682011-02-19 12:05:57 -03005292
Johan Hedberg744cf192011-11-08 20:40:14 +02005293 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005294 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005295}
5296
Johan Hedberg272d90d2012-02-09 15:26:12 +02005297int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005298 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005299{
5300 struct mgmt_ev_user_passkey_request ev;
5301
5302 BT_DBG("%s", hdev->name);
5303
Johan Hedberg272d90d2012-02-09 15:26:12 +02005304 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005305 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005306
5307 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005308 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005309}
5310
Brian Gix0df4c182011-11-16 13:53:13 -08005311static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005312 u8 link_type, u8 addr_type, u8 status,
5313 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005314{
5315 struct pending_cmd *cmd;
5316 struct mgmt_rp_user_confirm_reply rp;
5317 int err;
5318
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005319 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005320 if (!cmd)
5321 return -ENOENT;
5322
Johan Hedberg272d90d2012-02-09 15:26:12 +02005323 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005324 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005325 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005326 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005327
Johan Hedberga664b5b2011-02-19 12:06:02 -03005328 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005329
5330 return err;
5331}
5332
Johan Hedberg744cf192011-11-08 20:40:14 +02005333int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005334 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005335{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005336 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005337 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005338}
5339
Johan Hedberg272d90d2012-02-09 15:26:12 +02005340int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005341 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005342{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005343 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005344 status,
5345 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005346}
Johan Hedberg2a611692011-02-19 12:06:00 -03005347
Brian Gix604086b2011-11-23 08:28:33 -08005348int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005349 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005350{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005351 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005352 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005353}
5354
Johan Hedberg272d90d2012-02-09 15:26:12 +02005355int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005356 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005357{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005358 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005359 status,
5360 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005361}
5362
Johan Hedberg92a25252012-09-06 18:39:26 +03005363int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5364 u8 link_type, u8 addr_type, u32 passkey,
5365 u8 entered)
5366{
5367 struct mgmt_ev_passkey_notify ev;
5368
5369 BT_DBG("%s", hdev->name);
5370
5371 bacpy(&ev.addr.bdaddr, bdaddr);
5372 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5373 ev.passkey = __cpu_to_le32(passkey);
5374 ev.entered = entered;
5375
5376 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5377}
5378
Marcel Holtmanne5460992013-10-15 14:26:23 -07005379void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5380 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005381{
5382 struct mgmt_ev_auth_failed ev;
5383
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005384 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005385 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005386 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005387
Marcel Holtmanne5460992013-10-15 14:26:23 -07005388 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005389}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005390
Marcel Holtmann464996a2013-10-15 14:26:24 -07005391void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005392{
5393 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005394 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005395
5396 if (status) {
5397 u8 mgmt_err = mgmt_status(status);
5398 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005399 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005400 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005401 }
5402
Marcel Holtmann464996a2013-10-15 14:26:24 -07005403 if (test_bit(HCI_AUTH, &hdev->flags))
5404 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5405 &hdev->dev_flags);
5406 else
5407 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5408 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005409
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005410 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005411 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005412
Johan Hedberg47990ea2012-02-22 11:58:37 +02005413 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005414 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005415
5416 if (match.sk)
5417 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005418}
5419
Johan Hedberg890ea892013-03-15 17:06:52 -05005420static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005421{
Johan Hedberg890ea892013-03-15 17:06:52 -05005422 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005423 struct hci_cp_write_eir cp;
5424
Johan Hedberg976eb202012-10-24 21:12:01 +03005425 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005426 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005427
Johan Hedbergc80da272012-02-22 15:38:48 +02005428 memset(hdev->eir, 0, sizeof(hdev->eir));
5429
Johan Hedbergcacaf522012-02-21 00:52:42 +02005430 memset(&cp, 0, sizeof(cp));
5431
Johan Hedberg890ea892013-03-15 17:06:52 -05005432 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005433}
5434
Marcel Holtmann3e248562013-10-15 14:26:25 -07005435void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005436{
5437 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005438 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005439 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005440
5441 if (status) {
5442 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005443
5444 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005445 &hdev->dev_flags)) {
5446 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005447 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005448 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005449
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005450 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5451 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005452 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005453 }
5454
5455 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005456 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005457 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005458 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5459 if (!changed)
5460 changed = test_and_clear_bit(HCI_HS_ENABLED,
5461 &hdev->dev_flags);
5462 else
5463 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005464 }
5465
5466 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5467
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005468 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005469 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005470
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005471 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005472 sock_put(match.sk);
5473
Johan Hedberg890ea892013-03-15 17:06:52 -05005474 hci_req_init(&req, hdev);
5475
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005476 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005477 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005478 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005479 clear_eir(&req);
5480
5481 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005482}
5483
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005484void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5485{
5486 struct cmd_lookup match = { NULL, hdev };
5487 bool changed = false;
5488
5489 if (status) {
5490 u8 mgmt_err = mgmt_status(status);
5491
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005492 if (enable) {
5493 if (test_and_clear_bit(HCI_SC_ENABLED,
5494 &hdev->dev_flags))
5495 new_settings(hdev, NULL);
5496 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5497 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005498
5499 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5500 cmd_status_rsp, &mgmt_err);
5501 return;
5502 }
5503
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005504 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005505 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005506 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005507 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005508 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5509 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005510
5511 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5512 settings_rsp, &match);
5513
5514 if (changed)
5515 new_settings(hdev, match.sk);
5516
5517 if (match.sk)
5518 sock_put(match.sk);
5519}
5520
Johan Hedberg92da6092013-03-15 17:06:55 -05005521static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005522{
5523 struct cmd_lookup *match = data;
5524
Johan Hedberg90e70452012-02-23 23:09:40 +02005525 if (match->sk == NULL) {
5526 match->sk = cmd->sk;
5527 sock_hold(match->sk);
5528 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005529}
5530
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005531void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5532 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005533{
Johan Hedberg90e70452012-02-23 23:09:40 +02005534 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005535
Johan Hedberg92da6092013-03-15 17:06:55 -05005536 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5537 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5538 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005539
5540 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005541 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5542 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005543
5544 if (match.sk)
5545 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005546}
5547
Marcel Holtmann7667da32013-10-15 14:26:27 -07005548void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005549{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005550 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005551 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005552
Johan Hedberg13928972013-03-15 17:07:00 -05005553 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005554 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005555
5556 memset(&ev, 0, sizeof(ev));
5557 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005558 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005559
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005560 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005561 if (!cmd) {
5562 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005563
Johan Hedberg13928972013-03-15 17:07:00 -05005564 /* If this is a HCI command related to powering on the
5565 * HCI dev don't send any mgmt signals.
5566 */
5567 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005568 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005569 }
5570
Marcel Holtmann7667da32013-10-15 14:26:27 -07005571 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5572 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005573}
Szymon Jancc35938b2011-03-22 13:12:21 +01005574
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005575void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5576 u8 *randomizer192, u8 *hash256,
5577 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005578{
5579 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005580
Johan Hedberg744cf192011-11-08 20:40:14 +02005581 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005582
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005583 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005584 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005585 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005586
5587 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005588 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5589 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005590 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005591 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5592 hash256 && randomizer256) {
5593 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005594
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005595 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5596 memcpy(rp.randomizer192, randomizer192,
5597 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005598
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005599 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5600 memcpy(rp.randomizer256, randomizer256,
5601 sizeof(rp.randomizer256));
5602
5603 cmd_complete(cmd->sk, hdev->id,
5604 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5605 &rp, sizeof(rp));
5606 } else {
5607 struct mgmt_rp_read_local_oob_data rp;
5608
5609 memcpy(rp.hash, hash192, sizeof(rp.hash));
5610 memcpy(rp.randomizer, randomizer192,
5611 sizeof(rp.randomizer));
5612
5613 cmd_complete(cmd->sk, hdev->id,
5614 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5615 &rp, sizeof(rp));
5616 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005617 }
5618
5619 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005620}
Johan Hedberge17acd42011-03-30 23:57:16 +03005621
Marcel Holtmann901801b2013-10-06 23:55:51 -07005622void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5623 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
5624 ssp, u8 *eir, u16 eir_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005625{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005626 char buf[512];
5627 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005628 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005629 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005630
Andre Guedes12602d02013-04-30 15:29:40 -03005631 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005632 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005633
Johan Hedberg1dc06092012-01-15 21:01:23 +02005634 /* Leave 5 bytes for a potential CoD field */
5635 if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005636 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005637
Johan Hedberg1dc06092012-01-15 21:01:23 +02005638 memset(buf, 0, sizeof(buf));
5639
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005640 irk = hci_get_irk(hdev, bdaddr, addr_type);
5641 if (irk) {
5642 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5643 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5644 } else {
5645 bacpy(&ev->addr.bdaddr, bdaddr);
5646 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5647 }
5648
Johan Hedberge319d2e2012-01-15 19:51:59 +02005649 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005650 if (cfm_name)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305651 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005652 if (!ssp)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305653 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005654
Johan Hedberg1dc06092012-01-15 21:01:23 +02005655 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005656 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005657
Johan Hedberg1dc06092012-01-15 21:01:23 +02005658 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5659 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005660 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005661
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005662 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005663 ev_size = sizeof(*ev) + eir_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005664
Marcel Holtmann901801b2013-10-06 23:55:51 -07005665 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005666}
Johan Hedberga88a9652011-03-30 13:18:12 +03005667
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005668void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5669 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005670{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005671 struct mgmt_ev_device_found *ev;
5672 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5673 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005674
Johan Hedbergb644ba32012-01-17 21:48:47 +02005675 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005676
Johan Hedbergb644ba32012-01-17 21:48:47 +02005677 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005678
Johan Hedbergb644ba32012-01-17 21:48:47 +02005679 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005680 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005681 ev->rssi = rssi;
5682
5683 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005684 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005685
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005686 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005687
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005688 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005689}
Johan Hedberg314b2382011-04-27 10:29:57 -04005690
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005691void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005692{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005693 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005694 struct pending_cmd *cmd;
5695
Andre Guedes343fb142011-11-22 17:14:19 -03005696 BT_DBG("%s discovering %u", hdev->name, discovering);
5697
Johan Hedberg164a6e72011-11-01 17:06:44 +02005698 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005699 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005700 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005701 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005702
5703 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005704 u8 type = hdev->discovery.type;
5705
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005706 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5707 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005708 mgmt_pending_remove(cmd);
5709 }
5710
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005711 memset(&ev, 0, sizeof(ev));
5712 ev.type = hdev->discovery.type;
5713 ev.discovering = discovering;
5714
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005715 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04005716}
Antti Julku5e762442011-08-25 16:48:02 +03005717
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005718int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005719{
5720 struct pending_cmd *cmd;
5721 struct mgmt_ev_device_blocked ev;
5722
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005723 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005724
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005725 bacpy(&ev.addr.bdaddr, bdaddr);
5726 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005727
Johan Hedberg744cf192011-11-08 20:40:14 +02005728 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005729 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005730}
5731
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005732int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005733{
5734 struct pending_cmd *cmd;
5735 struct mgmt_ev_device_unblocked ev;
5736
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005737 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005738
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005739 bacpy(&ev.addr.bdaddr, bdaddr);
5740 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005741
Johan Hedberg744cf192011-11-08 20:40:14 +02005742 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005743 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005744}
Marcel Holtmann5976e602013-10-06 04:08:14 -07005745
5746static void adv_enable_complete(struct hci_dev *hdev, u8 status)
5747{
5748 BT_DBG("%s status %u", hdev->name, status);
5749
5750 /* Clear the advertising mgmt setting if we failed to re-enable it */
5751 if (status) {
5752 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005753 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005754 }
5755}
5756
5757void mgmt_reenable_advertising(struct hci_dev *hdev)
5758{
5759 struct hci_request req;
5760
Marcel Holtmannb145edc2013-10-10 09:47:54 -07005761 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07005762 return;
5763
5764 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5765 return;
5766
5767 hci_req_init(&req, hdev);
5768 enable_advertising(&req);
5769
5770 /* If this fails we have no option but to let user space know
5771 * that we've disabled advertising.
5772 */
5773 if (hci_req_run(&req, adv_enable_complete) < 0) {
5774 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005775 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005776 }
5777}