blob: 2d11c817d08214f5c8fffe1dfdcc9edee9e1aeb0 [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 Holtmann40456642014-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200208
Andre Guedes790eff42012-06-07 19:05:46 -0300209 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200225 kfree_skb(skb);
226
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300227 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200228}
229
Johan Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Holtmann5afeac12014-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200427
Johan Hedberg84bde9d6c2012-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 Hedbergf7b64e692010-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 Hedberg84bde9d6c2012-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 Hedbergaee9b212012-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
Johan Hedberga3172b72014-02-28 09:33:44 +02001034 if (hci_conn_count(hdev) == 0) {
1035 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001036 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001037 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001038}
1039
1040static int clean_up_hci_state(struct hci_dev *hdev)
1041{
1042 struct hci_request req;
1043 struct hci_conn *conn;
1044
1045 hci_req_init(&req, hdev);
1046
1047 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1048 test_bit(HCI_PSCAN, &hdev->flags)) {
1049 u8 scan = 0x00;
1050 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1051 }
1052
1053 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1054 disable_advertising(&req);
1055
1056 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Andre Guedesb1efcc22014-02-26 20:21:40 -03001057 hci_req_add_le_scan_disable(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001058 }
1059
1060 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1061 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001062 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001063
Johan Hedbergc9910d02014-02-27 14:35:12 +02001064 switch (conn->state) {
1065 case BT_CONNECTED:
1066 case BT_CONFIG:
1067 dc.handle = cpu_to_le16(conn->handle);
1068 dc.reason = 0x15; /* Terminated due to Power Off */
1069 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1070 break;
1071 case BT_CONNECT:
1072 if (conn->type == LE_LINK)
1073 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1074 0, NULL);
1075 else if (conn->type == ACL_LINK)
1076 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1077 6, &conn->dst);
1078 break;
1079 case BT_CONNECT2:
1080 bacpy(&rej.bdaddr, &conn->dst);
1081 rej.reason = 0x15; /* Terminated due to Power Off */
1082 if (conn->type == ACL_LINK)
1083 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1084 sizeof(rej), &rej);
1085 else if (conn->type == SCO_LINK)
1086 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1087 sizeof(rej), &rej);
1088 break;
1089 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001090 }
1091
1092 return hci_req_run(&req, clean_up_hci_complete);
1093}
1094
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001095static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001096 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001097{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001098 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001099 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001100 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001101
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001102 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001103
Johan Hedberga7e80f22013-01-09 16:05:19 +02001104 if (cp->val != 0x00 && cp->val != 0x01)
1105 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1106 MGMT_STATUS_INVALID_PARAMS);
1107
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001108 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001109
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001110 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1111 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1112 MGMT_STATUS_BUSY);
1113 goto failed;
1114 }
1115
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001116 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1117 cancel_delayed_work(&hdev->power_off);
1118
1119 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001120 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1121 data, len);
1122 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001123 goto failed;
1124 }
1125 }
1126
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001127 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001128 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001129 goto failed;
1130 }
1131
Johan Hedberg03811012010-12-08 00:21:06 +02001132 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1133 if (!cmd) {
1134 err = -ENOMEM;
1135 goto failed;
1136 }
1137
Johan Hedberg8b064a32014-02-24 14:52:22 +02001138 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001139 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001140 err = 0;
1141 } else {
1142 /* Disconnect connections, stop scans, etc */
1143 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001144 if (!err)
1145 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1146 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001147
Johan Hedberg8b064a32014-02-24 14:52:22 +02001148 /* ENODATA means there were no HCI commands queued */
1149 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001150 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001151 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1152 err = 0;
1153 }
1154 }
Johan Hedberg03811012010-12-08 00:21:06 +02001155
1156failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001157 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001158 return err;
1159}
1160
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001161static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1162 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001163{
1164 struct sk_buff *skb;
1165 struct mgmt_hdr *hdr;
1166
Andre Guedes790eff42012-06-07 19:05:46 -03001167 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001168 if (!skb)
1169 return -ENOMEM;
1170
1171 hdr = (void *) skb_put(skb, sizeof(*hdr));
1172 hdr->opcode = cpu_to_le16(event);
1173 if (hdev)
1174 hdr->index = cpu_to_le16(hdev->id);
1175 else
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05301176 hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001177 hdr->len = cpu_to_le16(data_len);
1178
1179 if (data)
1180 memcpy(skb_put(skb, data_len), data, data_len);
1181
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001182 /* Time stamp */
1183 __net_timestamp(skb);
1184
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001185 hci_send_to_control(skb, skip_sk);
1186 kfree_skb(skb);
1187
1188 return 0;
1189}
1190
1191static int new_settings(struct hci_dev *hdev, struct sock *skip)
1192{
1193 __le32 ev;
1194
1195 ev = cpu_to_le32(get_current_settings(hdev));
1196
1197 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1198}
1199
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001200struct cmd_lookup {
1201 struct sock *sk;
1202 struct hci_dev *hdev;
1203 u8 mgmt_status;
1204};
1205
1206static void settings_rsp(struct pending_cmd *cmd, void *data)
1207{
1208 struct cmd_lookup *match = data;
1209
1210 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1211
1212 list_del(&cmd->list);
1213
1214 if (match->sk == NULL) {
1215 match->sk = cmd->sk;
1216 sock_hold(match->sk);
1217 }
1218
1219 mgmt_pending_free(cmd);
1220}
1221
1222static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1223{
1224 u8 *status = data;
1225
1226 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1227 mgmt_pending_remove(cmd);
1228}
1229
Johan Hedberge6fe7982013-10-02 15:45:22 +03001230static u8 mgmt_bredr_support(struct hci_dev *hdev)
1231{
1232 if (!lmp_bredr_capable(hdev))
1233 return MGMT_STATUS_NOT_SUPPORTED;
1234 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1235 return MGMT_STATUS_REJECTED;
1236 else
1237 return MGMT_STATUS_SUCCESS;
1238}
1239
1240static u8 mgmt_le_support(struct hci_dev *hdev)
1241{
1242 if (!lmp_le_capable(hdev))
1243 return MGMT_STATUS_NOT_SUPPORTED;
1244 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1245 return MGMT_STATUS_REJECTED;
1246 else
1247 return MGMT_STATUS_SUCCESS;
1248}
1249
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001250static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1251{
1252 struct pending_cmd *cmd;
1253 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001254 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001255 bool changed;
1256
1257 BT_DBG("status 0x%02x", status);
1258
1259 hci_dev_lock(hdev);
1260
1261 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1262 if (!cmd)
1263 goto unlock;
1264
1265 if (status) {
1266 u8 mgmt_err = mgmt_status(status);
1267 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001268 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001269 goto remove_cmd;
1270 }
1271
1272 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001273 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001274 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1275 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001276
1277 if (hdev->discov_timeout > 0) {
1278 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1279 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1280 to);
1281 }
1282 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001283 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1284 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001285 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001286
1287 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1288
1289 if (changed)
1290 new_settings(hdev, cmd->sk);
1291
Marcel Holtmann970ba522013-10-15 06:33:57 -07001292 /* When the discoverable mode gets changed, make sure
1293 * that class of device has the limited discoverable
1294 * bit correctly set.
1295 */
1296 hci_req_init(&req, hdev);
1297 update_class(&req);
1298 hci_req_run(&req, NULL);
1299
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001300remove_cmd:
1301 mgmt_pending_remove(cmd);
1302
1303unlock:
1304 hci_dev_unlock(hdev);
1305}
1306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001307static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001308 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001309{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001310 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001311 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001312 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001313 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001314 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001315 int err;
1316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001317 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001318
Johan Hedberg9a43e252013-10-20 19:00:07 +03001319 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1320 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001321 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001322 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001323
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001324 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001325 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1326 MGMT_STATUS_INVALID_PARAMS);
1327
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001328 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001329
1330 /* Disabling discoverable requires that no timeout is set,
1331 * and enabling limited discoverable requires a timeout.
1332 */
1333 if ((cp->val == 0x00 && timeout > 0) ||
1334 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001335 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001336 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001337
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001338 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001339
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001340 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001341 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001342 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001343 goto failed;
1344 }
1345
1346 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001347 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
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_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001350 goto failed;
1351 }
1352
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001353 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001354 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001355 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001356 goto failed;
1357 }
1358
1359 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001360 bool changed = false;
1361
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001362 /* Setting limited discoverable when powered off is
1363 * not a valid operation since it requires a timeout
1364 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1365 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001366 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1367 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1368 changed = true;
1369 }
1370
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001371 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001372 if (err < 0)
1373 goto failed;
1374
1375 if (changed)
1376 err = new_settings(hdev, sk);
1377
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001378 goto failed;
1379 }
1380
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001381 /* If the current mode is the same, then just update the timeout
1382 * value with the new value. And if only the timeout gets updated,
1383 * then no need for any HCI transactions.
1384 */
1385 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1386 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1387 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001388 cancel_delayed_work(&hdev->discov_off);
1389 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001390
Marcel Holtmann36261542013-10-15 08:28:51 -07001391 if (cp->val && hdev->discov_timeout > 0) {
1392 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001393 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001394 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001395 }
1396
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001397 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001398 goto failed;
1399 }
1400
1401 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1402 if (!cmd) {
1403 err = -ENOMEM;
1404 goto failed;
1405 }
1406
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001407 /* Cancel any potential discoverable timeout that might be
1408 * still active and store new timeout value. The arming of
1409 * the timeout happens in the complete handler.
1410 */
1411 cancel_delayed_work(&hdev->discov_off);
1412 hdev->discov_timeout = timeout;
1413
Johan Hedbergb456f872013-10-19 23:38:22 +03001414 /* Limited discoverable mode */
1415 if (cp->val == 0x02)
1416 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1417 else
1418 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1419
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001420 hci_req_init(&req, hdev);
1421
Johan Hedberg9a43e252013-10-20 19:00:07 +03001422 /* The procedure for LE-only controllers is much simpler - just
1423 * update the advertising data.
1424 */
1425 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1426 goto update_ad;
1427
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001428 scan = SCAN_PAGE;
1429
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001430 if (cp->val) {
1431 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001432
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001433 if (cp->val == 0x02) {
1434 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001435 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001436 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1437 hci_cp.iac_lap[1] = 0x8b;
1438 hci_cp.iac_lap[2] = 0x9e;
1439 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1440 hci_cp.iac_lap[4] = 0x8b;
1441 hci_cp.iac_lap[5] = 0x9e;
1442 } else {
1443 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001444 hci_cp.num_iac = 1;
1445 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1446 hci_cp.iac_lap[1] = 0x8b;
1447 hci_cp.iac_lap[2] = 0x9e;
1448 }
1449
1450 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1451 (hci_cp.num_iac * 3) + 1, &hci_cp);
1452
1453 scan |= SCAN_INQUIRY;
1454 } else {
1455 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1456 }
1457
1458 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001459
Johan Hedberg9a43e252013-10-20 19:00:07 +03001460update_ad:
1461 update_adv_data(&req);
1462
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001463 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001464 if (err < 0)
1465 mgmt_pending_remove(cmd);
1466
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001467failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001468 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001469 return err;
1470}
1471
Johan Hedberg406d7802013-03-15 17:07:09 -05001472static void write_fast_connectable(struct hci_request *req, bool enable)
1473{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001474 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001475 struct hci_cp_write_page_scan_activity acp;
1476 u8 type;
1477
Johan Hedberg547003b2013-10-21 16:51:53 +03001478 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1479 return;
1480
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001481 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1482 return;
1483
Johan Hedberg406d7802013-03-15 17:07:09 -05001484 if (enable) {
1485 type = PAGE_SCAN_TYPE_INTERLACED;
1486
1487 /* 160 msec page scan interval */
1488 acp.interval = __constant_cpu_to_le16(0x0100);
1489 } else {
1490 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1491
1492 /* default 1.28 sec page scan */
1493 acp.interval = __constant_cpu_to_le16(0x0800);
1494 }
1495
1496 acp.window = __constant_cpu_to_le16(0x0012);
1497
Johan Hedbergbd98b992013-03-15 17:07:13 -05001498 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1499 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1500 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1501 sizeof(acp), &acp);
1502
1503 if (hdev->page_scan_type != type)
1504 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001505}
1506
Johan Hedberg2b76f452013-03-15 17:07:04 -05001507static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1508{
1509 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001510 struct mgmt_mode *cp;
1511 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001512
1513 BT_DBG("status 0x%02x", status);
1514
1515 hci_dev_lock(hdev);
1516
1517 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1518 if (!cmd)
1519 goto unlock;
1520
Johan Hedberg37438c12013-10-14 16:20:05 +03001521 if (status) {
1522 u8 mgmt_err = mgmt_status(status);
1523 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1524 goto remove_cmd;
1525 }
1526
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001527 cp = cmd->param;
1528 if (cp->val)
1529 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1530 else
1531 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1532
Johan Hedberg2b76f452013-03-15 17:07:04 -05001533 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1534
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001535 if (changed)
1536 new_settings(hdev, cmd->sk);
1537
Johan Hedberg37438c12013-10-14 16:20:05 +03001538remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001539 mgmt_pending_remove(cmd);
1540
1541unlock:
1542 hci_dev_unlock(hdev);
1543}
1544
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001545static int set_connectable_update_settings(struct hci_dev *hdev,
1546 struct sock *sk, u8 val)
1547{
1548 bool changed = false;
1549 int err;
1550
1551 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1552 changed = true;
1553
1554 if (val) {
1555 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1556 } else {
1557 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1558 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1559 }
1560
1561 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1562 if (err < 0)
1563 return err;
1564
1565 if (changed)
1566 return new_settings(hdev, sk);
1567
1568 return 0;
1569}
1570
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001571static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001572 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001573{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001574 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001575 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001576 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001577 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001578 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001581
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001582 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1583 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001584 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001585 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001586
Johan Hedberga7e80f22013-01-09 16:05:19 +02001587 if (cp->val != 0x00 && cp->val != 0x01)
1588 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1589 MGMT_STATUS_INVALID_PARAMS);
1590
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001591 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001592
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001593 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001594 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001595 goto failed;
1596 }
1597
1598 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001599 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001600 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001601 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001602 goto failed;
1603 }
1604
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001605 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1606 if (!cmd) {
1607 err = -ENOMEM;
1608 goto failed;
1609 }
1610
Johan Hedberg2b76f452013-03-15 17:07:04 -05001611 hci_req_init(&req, hdev);
1612
Johan Hedberg9a43e252013-10-20 19:00:07 +03001613 /* If BR/EDR is not enabled and we disable advertising as a
1614 * by-product of disabling connectable, we need to update the
1615 * advertising flags.
1616 */
1617 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1618 if (!cp->val) {
1619 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1620 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1621 }
1622 update_adv_data(&req);
1623 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001624 if (cp->val) {
1625 scan = SCAN_PAGE;
1626 } else {
1627 scan = 0;
1628
1629 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001630 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001631 cancel_delayed_work(&hdev->discov_off);
1632 }
1633
1634 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1635 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001636
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001637 /* If we're going from non-connectable to connectable or
1638 * vice-versa when fast connectable is enabled ensure that fast
1639 * connectable gets disabled. write_fast_connectable won't do
1640 * anything if the page scan parameters are already what they
1641 * should be.
1642 */
1643 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001644 write_fast_connectable(&req, false);
1645
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001646 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1647 hci_conn_num(hdev, LE_LINK) == 0) {
1648 disable_advertising(&req);
1649 enable_advertising(&req);
1650 }
1651
Johan Hedberg2b76f452013-03-15 17:07:04 -05001652 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001653 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001654 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001655 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001656 err = set_connectable_update_settings(hdev, sk,
1657 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001658 goto failed;
1659 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001660
1661failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001662 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001663 return err;
1664}
1665
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001666static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001667 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001668{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001669 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001670 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001671 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001672
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001673 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001674
Johan Hedberga7e80f22013-01-09 16:05:19 +02001675 if (cp->val != 0x00 && cp->val != 0x01)
1676 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1677 MGMT_STATUS_INVALID_PARAMS);
1678
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001679 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001680
1681 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001682 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001683 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001684 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001685
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001686 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001687 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001688 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001689
Marcel Holtmann55594352013-10-06 16:11:57 -07001690 if (changed)
1691 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001692
Marcel Holtmann55594352013-10-06 16:11:57 -07001693unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001694 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001695 return err;
1696}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001697
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001698static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1699 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001700{
1701 struct mgmt_mode *cp = data;
1702 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001703 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001704 int err;
1705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001706 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001707
Johan Hedberge6fe7982013-10-02 15:45:22 +03001708 status = mgmt_bredr_support(hdev);
1709 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001710 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001711 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001712
Johan Hedberga7e80f22013-01-09 16:05:19 +02001713 if (cp->val != 0x00 && cp->val != 0x01)
1714 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1715 MGMT_STATUS_INVALID_PARAMS);
1716
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001717 hci_dev_lock(hdev);
1718
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001719 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001720 bool changed = false;
1721
1722 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001723 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001724 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1725 changed = true;
1726 }
1727
1728 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1729 if (err < 0)
1730 goto failed;
1731
1732 if (changed)
1733 err = new_settings(hdev, sk);
1734
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001735 goto failed;
1736 }
1737
1738 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001739 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001740 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001741 goto failed;
1742 }
1743
1744 val = !!cp->val;
1745
1746 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1747 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1748 goto failed;
1749 }
1750
1751 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1752 if (!cmd) {
1753 err = -ENOMEM;
1754 goto failed;
1755 }
1756
1757 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1758 if (err < 0) {
1759 mgmt_pending_remove(cmd);
1760 goto failed;
1761 }
1762
1763failed:
1764 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001765 return err;
1766}
1767
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001768static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001769{
1770 struct mgmt_mode *cp = data;
1771 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001772 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001773 int err;
1774
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001775 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001776
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001777 status = mgmt_bredr_support(hdev);
1778 if (status)
1779 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1780
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001781 if (!lmp_ssp_capable(hdev))
1782 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1783 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001784
Johan Hedberga7e80f22013-01-09 16:05:19 +02001785 if (cp->val != 0x00 && cp->val != 0x01)
1786 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1787 MGMT_STATUS_INVALID_PARAMS);
1788
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001789 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001790
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001791 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001792 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001793
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001794 if (cp->val) {
1795 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1796 &hdev->dev_flags);
1797 } else {
1798 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1799 &hdev->dev_flags);
1800 if (!changed)
1801 changed = test_and_clear_bit(HCI_HS_ENABLED,
1802 &hdev->dev_flags);
1803 else
1804 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001805 }
1806
1807 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1808 if (err < 0)
1809 goto failed;
1810
1811 if (changed)
1812 err = new_settings(hdev, sk);
1813
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001814 goto failed;
1815 }
1816
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001817 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1818 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001819 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1820 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001821 goto failed;
1822 }
1823
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001824 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001825 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1826 goto failed;
1827 }
1828
1829 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1830 if (!cmd) {
1831 err = -ENOMEM;
1832 goto failed;
1833 }
1834
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001835 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001836 if (err < 0) {
1837 mgmt_pending_remove(cmd);
1838 goto failed;
1839 }
1840
1841failed:
1842 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001843 return err;
1844}
1845
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001846static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001847{
1848 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001849 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001850 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001851 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001852
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001853 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001854
Johan Hedberge6fe7982013-10-02 15:45:22 +03001855 status = mgmt_bredr_support(hdev);
1856 if (status)
1857 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001858
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001859 if (!lmp_ssp_capable(hdev))
1860 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1861 MGMT_STATUS_NOT_SUPPORTED);
1862
1863 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1864 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1865 MGMT_STATUS_REJECTED);
1866
Johan Hedberga7e80f22013-01-09 16:05:19 +02001867 if (cp->val != 0x00 && cp->val != 0x01)
1868 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1869 MGMT_STATUS_INVALID_PARAMS);
1870
Marcel Holtmannee392692013-10-01 22:59:23 -07001871 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001872
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001873 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001874 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001875 } else {
1876 if (hdev_is_powered(hdev)) {
1877 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1878 MGMT_STATUS_REJECTED);
1879 goto unlock;
1880 }
1881
Marcel Holtmannee392692013-10-01 22:59:23 -07001882 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001883 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001884
1885 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1886 if (err < 0)
1887 goto unlock;
1888
1889 if (changed)
1890 err = new_settings(hdev, sk);
1891
1892unlock:
1893 hci_dev_unlock(hdev);
1894 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001895}
1896
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001897static void le_enable_complete(struct hci_dev *hdev, u8 status)
1898{
1899 struct cmd_lookup match = { NULL, hdev };
1900
1901 if (status) {
1902 u8 mgmt_err = mgmt_status(status);
1903
1904 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1905 &mgmt_err);
1906 return;
1907 }
1908
1909 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1910
1911 new_settings(hdev, match.sk);
1912
1913 if (match.sk)
1914 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001915
1916 /* Make sure the controller has a good default for
1917 * advertising data. Restrict the update to when LE
1918 * has actually been enabled. During power on, the
1919 * update in powered_update_hci will take care of it.
1920 */
1921 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1922 struct hci_request req;
1923
1924 hci_dev_lock(hdev);
1925
1926 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001927 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001928 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001929 hci_req_run(&req, NULL);
1930
1931 hci_dev_unlock(hdev);
1932 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001933}
1934
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001935static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001936{
1937 struct mgmt_mode *cp = data;
1938 struct hci_cp_write_le_host_supported hci_cp;
1939 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001940 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001941 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001942 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001943
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001944 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001945
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001946 if (!lmp_le_capable(hdev))
1947 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1948 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001949
Johan Hedberga7e80f22013-01-09 16:05:19 +02001950 if (cp->val != 0x00 && cp->val != 0x01)
1951 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1952 MGMT_STATUS_INVALID_PARAMS);
1953
Johan Hedbergc73eee92013-04-19 18:35:21 +03001954 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03001955 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03001956 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1957 MGMT_STATUS_REJECTED);
1958
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001959 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001960
1961 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001962 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001963
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001964 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02001965 bool changed = false;
1966
1967 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1968 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1969 changed = true;
1970 }
1971
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02001972 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
1973 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03001974 changed = true;
1975 }
1976
Johan Hedberg06199cf2012-02-22 16:37:11 +02001977 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1978 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08001979 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001980
1981 if (changed)
1982 err = new_settings(hdev, sk);
1983
Johan Hedberg1de028c2012-02-29 19:55:35 -08001984 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001985 }
1986
Johan Hedberg4375f102013-09-25 13:26:10 +03001987 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
1988 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001989 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001990 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001991 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001992 }
1993
1994 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
1995 if (!cmd) {
1996 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08001997 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001998 }
1999
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002000 hci_req_init(&req, hdev);
2001
Johan Hedberg06199cf2012-02-22 16:37:11 +02002002 memset(&hci_cp, 0, sizeof(hci_cp));
2003
2004 if (val) {
2005 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002006 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002007 } else {
2008 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2009 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002010 }
2011
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002012 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2013 &hci_cp);
2014
2015 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302016 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002017 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002018
Johan Hedberg1de028c2012-02-29 19:55:35 -08002019unlock:
2020 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002021 return err;
2022}
2023
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002024/* This is a helper function to test for pending mgmt commands that can
2025 * cause CoD or EIR HCI commands. We can only allow one such pending
2026 * mgmt command at a time since otherwise we cannot easily track what
2027 * the current values are, will be, and based on that calculate if a new
2028 * HCI command needs to be sent and if yes with what value.
2029 */
2030static bool pending_eir_or_class(struct hci_dev *hdev)
2031{
2032 struct pending_cmd *cmd;
2033
2034 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2035 switch (cmd->opcode) {
2036 case MGMT_OP_ADD_UUID:
2037 case MGMT_OP_REMOVE_UUID:
2038 case MGMT_OP_SET_DEV_CLASS:
2039 case MGMT_OP_SET_POWERED:
2040 return true;
2041 }
2042 }
2043
2044 return false;
2045}
2046
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002047static const u8 bluetooth_base_uuid[] = {
2048 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2049 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2050};
2051
2052static u8 get_uuid_size(const u8 *uuid)
2053{
2054 u32 val;
2055
2056 if (memcmp(uuid, bluetooth_base_uuid, 12))
2057 return 128;
2058
2059 val = get_unaligned_le32(&uuid[12]);
2060 if (val > 0xffff)
2061 return 32;
2062
2063 return 16;
2064}
2065
Johan Hedberg92da6092013-03-15 17:06:55 -05002066static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2067{
2068 struct pending_cmd *cmd;
2069
2070 hci_dev_lock(hdev);
2071
2072 cmd = mgmt_pending_find(mgmt_op, hdev);
2073 if (!cmd)
2074 goto unlock;
2075
2076 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2077 hdev->dev_class, 3);
2078
2079 mgmt_pending_remove(cmd);
2080
2081unlock:
2082 hci_dev_unlock(hdev);
2083}
2084
2085static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2086{
2087 BT_DBG("status 0x%02x", status);
2088
2089 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2090}
2091
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002092static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002093{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002094 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002095 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002096 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002097 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002098 int err;
2099
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002100 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002101
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002102 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002103
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002104 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002105 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002106 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002107 goto failed;
2108 }
2109
Andre Guedes92c4c202012-06-07 19:05:44 -03002110 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002111 if (!uuid) {
2112 err = -ENOMEM;
2113 goto failed;
2114 }
2115
2116 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002117 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002118 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002119
Johan Hedbergde66aa62013-01-27 00:31:27 +02002120 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002121
Johan Hedberg890ea892013-03-15 17:06:52 -05002122 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002123
Johan Hedberg890ea892013-03-15 17:06:52 -05002124 update_class(&req);
2125 update_eir(&req);
2126
Johan Hedberg92da6092013-03-15 17:06:55 -05002127 err = hci_req_run(&req, add_uuid_complete);
2128 if (err < 0) {
2129 if (err != -ENODATA)
2130 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002131
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002132 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002133 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002134 goto failed;
2135 }
2136
2137 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002138 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002139 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002140 goto failed;
2141 }
2142
2143 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002144
2145failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002146 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002147 return err;
2148}
2149
Johan Hedberg24b78d02012-02-23 23:24:30 +02002150static bool enable_service_cache(struct hci_dev *hdev)
2151{
2152 if (!hdev_is_powered(hdev))
2153 return false;
2154
2155 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002156 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2157 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002158 return true;
2159 }
2160
2161 return false;
2162}
2163
Johan Hedberg92da6092013-03-15 17:06:55 -05002164static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2165{
2166 BT_DBG("status 0x%02x", status);
2167
2168 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2169}
2170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002171static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002172 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002173{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002174 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002175 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002176 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002177 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 -05002178 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002179 int err, found;
2180
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002181 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002183 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002184
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002185 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002186 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002187 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002188 goto unlock;
2189 }
2190
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002191 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002192 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002193
Johan Hedberg24b78d02012-02-23 23:24:30 +02002194 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002195 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002196 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002197 goto unlock;
2198 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002199
Johan Hedberg9246a862012-02-23 21:33:16 +02002200 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002201 }
2202
2203 found = 0;
2204
Johan Hedberg056341c2013-01-27 00:31:30 +02002205 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002206 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2207 continue;
2208
2209 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002210 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002211 found++;
2212 }
2213
2214 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002215 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002216 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002217 goto unlock;
2218 }
2219
Johan Hedberg9246a862012-02-23 21:33:16 +02002220update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002221 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002222
Johan Hedberg890ea892013-03-15 17:06:52 -05002223 update_class(&req);
2224 update_eir(&req);
2225
Johan Hedberg92da6092013-03-15 17:06:55 -05002226 err = hci_req_run(&req, remove_uuid_complete);
2227 if (err < 0) {
2228 if (err != -ENODATA)
2229 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002230
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002231 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002232 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002233 goto unlock;
2234 }
2235
2236 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002237 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002238 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002239 goto unlock;
2240 }
2241
2242 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002243
2244unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002245 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002246 return err;
2247}
2248
Johan Hedberg92da6092013-03-15 17:06:55 -05002249static void set_class_complete(struct hci_dev *hdev, u8 status)
2250{
2251 BT_DBG("status 0x%02x", status);
2252
2253 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2254}
2255
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002256static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002257 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002258{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002259 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002260 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002261 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002262 int err;
2263
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002264 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002265
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002266 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002267 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2268 MGMT_STATUS_NOT_SUPPORTED);
2269
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002270 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002271
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002272 if (pending_eir_or_class(hdev)) {
2273 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2274 MGMT_STATUS_BUSY);
2275 goto unlock;
2276 }
2277
2278 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2279 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2280 MGMT_STATUS_INVALID_PARAMS);
2281 goto unlock;
2282 }
2283
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002284 hdev->major_class = cp->major;
2285 hdev->minor_class = cp->minor;
2286
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002287 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002288 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002289 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002290 goto unlock;
2291 }
2292
Johan Hedberg890ea892013-03-15 17:06:52 -05002293 hci_req_init(&req, hdev);
2294
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002295 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002296 hci_dev_unlock(hdev);
2297 cancel_delayed_work_sync(&hdev->service_cache);
2298 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002299 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002300 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002301
Johan Hedberg890ea892013-03-15 17:06:52 -05002302 update_class(&req);
2303
Johan Hedberg92da6092013-03-15 17:06:55 -05002304 err = hci_req_run(&req, set_class_complete);
2305 if (err < 0) {
2306 if (err != -ENODATA)
2307 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002309 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002310 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002311 goto unlock;
2312 }
2313
2314 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002315 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002316 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002317 goto unlock;
2318 }
2319
2320 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002321
Johan Hedbergb5235a62012-02-21 14:32:24 +02002322unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002323 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002324 return err;
2325}
2326
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002327static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002328 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002329{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002330 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002331 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002332 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002333 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002334
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002335 BT_DBG("request for %s", hdev->name);
2336
2337 if (!lmp_bredr_capable(hdev))
2338 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2339 MGMT_STATUS_NOT_SUPPORTED);
2340
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002341 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002342
Johan Hedberg86742e12011-11-07 23:13:38 +02002343 expected_len = sizeof(*cp) + key_count *
2344 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002345 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002346 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002347 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002348 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002349 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002350 }
2351
Johan Hedberg4ae14302013-01-20 14:27:13 +02002352 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2353 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2354 MGMT_STATUS_INVALID_PARAMS);
2355
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002356 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002357 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002358
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002359 for (i = 0; i < key_count; i++) {
2360 struct mgmt_link_key_info *key = &cp->keys[i];
2361
Marcel Holtmann8e991132014-01-10 02:07:25 -08002362 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002363 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2364 MGMT_STATUS_INVALID_PARAMS);
2365 }
2366
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002367 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002368
2369 hci_link_keys_clear(hdev);
2370
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002371 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002372 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002373 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002374 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2375
2376 if (changed)
2377 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002378
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002379 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002380 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002381
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002382 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002383 key->type, key->pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002384 }
2385
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002386 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002387
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002388 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002389
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002390 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002391}
2392
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002393static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002394 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002395{
2396 struct mgmt_ev_device_unpaired ev;
2397
2398 bacpy(&ev.addr.bdaddr, bdaddr);
2399 ev.addr.type = addr_type;
2400
2401 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002402 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002403}
2404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002405static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002406 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002407{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002408 struct mgmt_cp_unpair_device *cp = data;
2409 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002410 struct hci_cp_disconnect dc;
2411 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002412 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002413 int err;
2414
Johan Hedberga8a1d192011-11-10 15:54:38 +02002415 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002416 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2417 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002418
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002419 if (!bdaddr_type_is_valid(cp->addr.type))
2420 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2421 MGMT_STATUS_INVALID_PARAMS,
2422 &rp, sizeof(rp));
2423
Johan Hedberg118da702013-01-20 14:27:20 +02002424 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2425 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2426 MGMT_STATUS_INVALID_PARAMS,
2427 &rp, sizeof(rp));
2428
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002429 hci_dev_lock(hdev);
2430
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002431 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002432 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002433 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002434 goto unlock;
2435 }
2436
Johan Hedberge0b2b272014-02-18 17:14:31 +02002437 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002438 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002439 } else {
2440 u8 addr_type;
2441
2442 if (cp->addr.type == BDADDR_LE_PUBLIC)
2443 addr_type = ADDR_LE_DEV_PUBLIC;
2444 else
2445 addr_type = ADDR_LE_DEV_RANDOM;
2446
Johan Hedberga7ec7332014-02-18 17:14:35 +02002447 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2448
Andre Guedesa9b0a042014-02-26 20:21:52 -03002449 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2450
Johan Hedberge0b2b272014-02-18 17:14:31 +02002451 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2452 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002453
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002454 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002455 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002456 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002457 goto unlock;
2458 }
2459
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002460 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002461 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002462 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002463 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002464 else
2465 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002466 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002467 } else {
2468 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002469 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002470
Johan Hedberga8a1d192011-11-10 15:54:38 +02002471 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002472 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002473 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002474 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002475 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002476 }
2477
Johan Hedberg124f6e32012-02-09 13:50:12 +02002478 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002479 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002480 if (!cmd) {
2481 err = -ENOMEM;
2482 goto unlock;
2483 }
2484
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002485 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002486 dc.reason = 0x13; /* Remote User Terminated Connection */
2487 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2488 if (err < 0)
2489 mgmt_pending_remove(cmd);
2490
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002491unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002492 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002493 return err;
2494}
2495
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002496static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002497 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002498{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002499 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002500 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002501 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002502 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002503 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002504 int err;
2505
2506 BT_DBG("");
2507
Johan Hedberg06a63b12013-01-20 14:27:21 +02002508 memset(&rp, 0, sizeof(rp));
2509 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2510 rp.addr.type = cp->addr.type;
2511
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002512 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002513 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2514 MGMT_STATUS_INVALID_PARAMS,
2515 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002516
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002517 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002518
2519 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002520 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2521 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002522 goto failed;
2523 }
2524
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002525 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002526 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2527 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002528 goto failed;
2529 }
2530
Andre Guedes591f47f2012-04-24 21:02:49 -03002531 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002532 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2533 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002534 else
2535 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002536
Vishal Agarwalf9607272012-06-13 05:32:43 +05302537 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002538 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2539 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002540 goto failed;
2541 }
2542
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002543 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002544 if (!cmd) {
2545 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002546 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002547 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002548
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002549 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002550 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002551
2552 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2553 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002554 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002555
2556failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002557 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002558 return err;
2559}
2560
Andre Guedes57c14772012-04-24 21:02:50 -03002561static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002562{
2563 switch (link_type) {
2564 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002565 switch (addr_type) {
2566 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002567 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002568
Johan Hedberg48264f02011-11-09 13:58:58 +02002569 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002570 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002571 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002572 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002573
Johan Hedberg4c659c32011-11-07 23:13:39 +02002574 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002575 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002576 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002577 }
2578}
2579
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002580static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2581 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002582{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002583 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002584 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002585 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002586 int err;
2587 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002588
2589 BT_DBG("");
2590
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002591 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002592
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002593 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002594 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002595 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002596 goto unlock;
2597 }
2598
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002599 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002600 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2601 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002602 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002603 }
2604
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002605 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002606 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002607 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002608 err = -ENOMEM;
2609 goto unlock;
2610 }
2611
Johan Hedberg2784eb42011-01-21 13:56:35 +02002612 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002613 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002614 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2615 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002616 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002617 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002618 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002619 continue;
2620 i++;
2621 }
2622
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002623 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002624
Johan Hedberg4c659c32011-11-07 23:13:39 +02002625 /* Recalculate length in case of filtered SCO connections, etc */
2626 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002627
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002628 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002629 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002630
Johan Hedberga38528f2011-01-22 06:46:43 +02002631 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002632
2633unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002634 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002635 return err;
2636}
2637
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002638static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002639 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002640{
2641 struct pending_cmd *cmd;
2642 int err;
2643
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002644 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002645 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002646 if (!cmd)
2647 return -ENOMEM;
2648
Johan Hedbergd8457692012-02-17 14:24:57 +02002649 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002650 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002651 if (err < 0)
2652 mgmt_pending_remove(cmd);
2653
2654 return err;
2655}
2656
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002657static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002658 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002659{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002660 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002661 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002662 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002663 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002664 int err;
2665
2666 BT_DBG("");
2667
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002668 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002669
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002670 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002671 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002672 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002673 goto failed;
2674 }
2675
Johan Hedbergd8457692012-02-17 14:24:57 +02002676 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002677 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002678 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002679 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002680 goto failed;
2681 }
2682
2683 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002684 struct mgmt_cp_pin_code_neg_reply ncp;
2685
2686 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002687
2688 BT_ERR("PIN code is not 16 bytes long");
2689
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002690 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002691 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002692 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002693 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002694
2695 goto failed;
2696 }
2697
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002698 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002699 if (!cmd) {
2700 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002701 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002702 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002703
Johan Hedbergd8457692012-02-17 14:24:57 +02002704 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002705 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002706 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002707
2708 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2709 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002710 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002711
2712failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002713 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002714 return err;
2715}
2716
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002717static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2718 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002719{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002720 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002721
2722 BT_DBG("");
2723
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002724 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002725
2726 hdev->io_capability = cp->io_capability;
2727
2728 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002729 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002730
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002731 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002732
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002733 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2734 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002735}
2736
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002737static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002738{
2739 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002740 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002741
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002742 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002743 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2744 continue;
2745
Johan Hedberge9a416b2011-02-19 12:05:56 -03002746 if (cmd->user_data != conn)
2747 continue;
2748
2749 return cmd;
2750 }
2751
2752 return NULL;
2753}
2754
2755static void pairing_complete(struct pending_cmd *cmd, u8 status)
2756{
2757 struct mgmt_rp_pair_device rp;
2758 struct hci_conn *conn = cmd->user_data;
2759
Johan Hedbergba4e5642011-11-11 00:07:34 +02002760 bacpy(&rp.addr.bdaddr, &conn->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002761 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002762
Johan Hedbergaee9b212012-02-18 15:07:59 +02002763 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002764 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002765
2766 /* So we don't get further callbacks for this connection */
2767 conn->connect_cfm_cb = NULL;
2768 conn->security_cfm_cb = NULL;
2769 conn->disconn_cfm_cb = NULL;
2770
David Herrmann76a68ba2013-04-06 20:28:37 +02002771 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002772
Johan Hedberga664b5b2011-02-19 12:06:02 -03002773 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002774}
2775
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002776void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2777{
2778 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2779 struct pending_cmd *cmd;
2780
2781 cmd = find_pairing(conn);
2782 if (cmd)
2783 pairing_complete(cmd, status);
2784}
2785
Johan Hedberge9a416b2011-02-19 12:05:56 -03002786static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2787{
2788 struct pending_cmd *cmd;
2789
2790 BT_DBG("status %u", status);
2791
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002792 cmd = find_pairing(conn);
2793 if (!cmd)
2794 BT_DBG("Unable to find a pending command");
2795 else
Johan Hedberge2113262012-02-18 15:20:03 +02002796 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002797}
2798
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002799static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302800{
2801 struct pending_cmd *cmd;
2802
2803 BT_DBG("status %u", status);
2804
2805 if (!status)
2806 return;
2807
2808 cmd = find_pairing(conn);
2809 if (!cmd)
2810 BT_DBG("Unable to find a pending command");
2811 else
2812 pairing_complete(cmd, mgmt_status(status));
2813}
2814
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002815static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002816 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002817{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002818 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002819 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002820 struct pending_cmd *cmd;
2821 u8 sec_level, auth_type;
2822 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002823 int err;
2824
2825 BT_DBG("");
2826
Szymon Jancf950a30e2013-01-18 12:48:07 +01002827 memset(&rp, 0, sizeof(rp));
2828 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2829 rp.addr.type = cp->addr.type;
2830
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002831 if (!bdaddr_type_is_valid(cp->addr.type))
2832 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2833 MGMT_STATUS_INVALID_PARAMS,
2834 &rp, sizeof(rp));
2835
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002836 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002837
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002838 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002839 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2840 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002841 goto unlock;
2842 }
2843
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002844 sec_level = BT_SECURITY_MEDIUM;
2845 if (cp->io_cap == 0x03)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002846 auth_type = HCI_AT_DEDICATED_BONDING;
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002847 else
Johan Hedberge9a416b2011-02-19 12:05:56 -03002848 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002849
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002850 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002851 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2852 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002853 } else {
2854 u8 addr_type;
2855
2856 /* Convert from L2CAP channel address type to HCI address type
2857 */
2858 if (cp->addr.type == BDADDR_LE_PUBLIC)
2859 addr_type = ADDR_LE_DEV_PUBLIC;
2860 else
2861 addr_type = ADDR_LE_DEV_RANDOM;
2862
2863 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002864 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002865 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002866
Ville Tervo30e76272011-02-22 16:10:53 -03002867 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002868 int status;
2869
2870 if (PTR_ERR(conn) == -EBUSY)
2871 status = MGMT_STATUS_BUSY;
2872 else
2873 status = MGMT_STATUS_CONNECT_FAILED;
2874
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002875 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002876 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002877 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002878 goto unlock;
2879 }
2880
2881 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002882 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002883 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002884 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002885 goto unlock;
2886 }
2887
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002888 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002889 if (!cmd) {
2890 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002891 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002892 goto unlock;
2893 }
2894
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002895 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002896 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002897 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002898 conn->security_cfm_cb = pairing_complete_cb;
2899 conn->disconn_cfm_cb = pairing_complete_cb;
2900 } else {
2901 conn->connect_cfm_cb = le_pairing_complete_cb;
2902 conn->security_cfm_cb = le_pairing_complete_cb;
2903 conn->disconn_cfm_cb = le_pairing_complete_cb;
2904 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002905
Johan Hedberge9a416b2011-02-19 12:05:56 -03002906 conn->io_capability = cp->io_cap;
2907 cmd->user_data = conn;
2908
2909 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002910 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002911 pairing_complete(cmd, 0);
2912
2913 err = 0;
2914
2915unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002916 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002917 return err;
2918}
2919
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002920static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2921 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002922{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002923 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002924 struct pending_cmd *cmd;
2925 struct hci_conn *conn;
2926 int err;
2927
2928 BT_DBG("");
2929
Johan Hedberg28424702012-02-02 04:02:29 +02002930 hci_dev_lock(hdev);
2931
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002932 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002933 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002934 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002935 goto unlock;
2936 }
2937
Johan Hedberg28424702012-02-02 04:02:29 +02002938 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2939 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002940 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002941 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002942 goto unlock;
2943 }
2944
2945 conn = cmd->user_data;
2946
2947 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002948 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002949 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002950 goto unlock;
2951 }
2952
2953 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2954
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002955 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002956 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02002957unlock:
2958 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02002959 return err;
2960}
2961
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002962static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05002963 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002964 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03002965{
Johan Hedberga5c29682011-02-19 12:05:57 -03002966 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08002967 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002968 int err;
2969
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002970 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02002971
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002972 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002973 err = cmd_complete(sk, hdev->id, mgmt_op,
2974 MGMT_STATUS_NOT_POWERED, addr,
2975 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08002976 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002977 }
2978
Johan Hedberg1707c602013-03-15 17:07:15 -05002979 if (addr->type == BDADDR_BREDR)
2980 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02002981 else
Johan Hedberg1707c602013-03-15 17:07:15 -05002982 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08002983
Johan Hedberg272d90d2012-02-09 15:26:12 +02002984 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002985 err = cmd_complete(sk, hdev->id, mgmt_op,
2986 MGMT_STATUS_NOT_CONNECTED, addr,
2987 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02002988 goto done;
2989 }
2990
Johan Hedberg1707c602013-03-15 17:07:15 -05002991 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08002992 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08002993 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08002994
Brian Gix5fe57d92011-12-21 16:12:13 -08002995 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002996 err = cmd_complete(sk, hdev->id, mgmt_op,
2997 MGMT_STATUS_SUCCESS, addr,
2998 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08002999 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003000 err = cmd_complete(sk, hdev->id, mgmt_op,
3001 MGMT_STATUS_FAILED, addr,
3002 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003003
Brian Gix47c15e22011-11-16 13:53:14 -08003004 goto done;
3005 }
3006
Johan Hedberg1707c602013-03-15 17:07:15 -05003007 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003008 if (!cmd) {
3009 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003010 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003011 }
3012
Brian Gix0df4c182011-11-16 13:53:13 -08003013 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003014 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3015 struct hci_cp_user_passkey_reply cp;
3016
Johan Hedberg1707c602013-03-15 17:07:15 -05003017 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003018 cp.passkey = passkey;
3019 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3020 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003021 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3022 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003023
Johan Hedberga664b5b2011-02-19 12:06:02 -03003024 if (err < 0)
3025 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003026
Brian Gix0df4c182011-11-16 13:53:13 -08003027done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003028 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003029 return err;
3030}
3031
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303032static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3033 void *data, u16 len)
3034{
3035 struct mgmt_cp_pin_code_neg_reply *cp = data;
3036
3037 BT_DBG("");
3038
Johan Hedberg1707c602013-03-15 17:07:15 -05003039 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303040 MGMT_OP_PIN_CODE_NEG_REPLY,
3041 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3042}
3043
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003044static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3045 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003046{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003047 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003048
3049 BT_DBG("");
3050
3051 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003052 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003053 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003054
Johan Hedberg1707c602013-03-15 17:07:15 -05003055 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003056 MGMT_OP_USER_CONFIRM_REPLY,
3057 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003058}
3059
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003060static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003061 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003062{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003063 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003064
3065 BT_DBG("");
3066
Johan Hedberg1707c602013-03-15 17:07:15 -05003067 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003068 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3069 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003070}
3071
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003072static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3073 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003074{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003075 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003076
3077 BT_DBG("");
3078
Johan Hedberg1707c602013-03-15 17:07:15 -05003079 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003080 MGMT_OP_USER_PASSKEY_REPLY,
3081 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003082}
3083
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003084static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003085 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003086{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003087 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003088
3089 BT_DBG("");
3090
Johan Hedberg1707c602013-03-15 17:07:15 -05003091 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003092 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3093 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003094}
3095
Johan Hedberg13928972013-03-15 17:07:00 -05003096static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003097{
Johan Hedberg13928972013-03-15 17:07:00 -05003098 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003099 struct hci_cp_write_local_name cp;
3100
Johan Hedberg13928972013-03-15 17:07:00 -05003101 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003102
Johan Hedberg890ea892013-03-15 17:06:52 -05003103 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003104}
3105
Johan Hedberg13928972013-03-15 17:07:00 -05003106static void set_name_complete(struct hci_dev *hdev, u8 status)
3107{
3108 struct mgmt_cp_set_local_name *cp;
3109 struct pending_cmd *cmd;
3110
3111 BT_DBG("status 0x%02x", status);
3112
3113 hci_dev_lock(hdev);
3114
3115 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3116 if (!cmd)
3117 goto unlock;
3118
3119 cp = cmd->param;
3120
3121 if (status)
3122 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3123 mgmt_status(status));
3124 else
3125 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3126 cp, sizeof(*cp));
3127
3128 mgmt_pending_remove(cmd);
3129
3130unlock:
3131 hci_dev_unlock(hdev);
3132}
3133
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003134static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003135 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003136{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003137 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003138 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003139 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003140 int err;
3141
3142 BT_DBG("");
3143
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003144 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003145
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003146 /* If the old values are the same as the new ones just return a
3147 * direct command complete event.
3148 */
3149 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3150 !memcmp(hdev->short_name, cp->short_name,
3151 sizeof(hdev->short_name))) {
3152 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3153 data, len);
3154 goto failed;
3155 }
3156
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003157 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003158
Johan Hedbergb5235a62012-02-21 14:32:24 +02003159 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003160 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003161
3162 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003163 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003164 if (err < 0)
3165 goto failed;
3166
3167 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003168 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003169
Johan Hedbergb5235a62012-02-21 14:32:24 +02003170 goto failed;
3171 }
3172
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003173 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003174 if (!cmd) {
3175 err = -ENOMEM;
3176 goto failed;
3177 }
3178
Johan Hedberg13928972013-03-15 17:07:00 -05003179 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3180
Johan Hedberg890ea892013-03-15 17:06:52 -05003181 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003182
3183 if (lmp_bredr_capable(hdev)) {
3184 update_name(&req);
3185 update_eir(&req);
3186 }
3187
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003188 /* The name is stored in the scan response data and so
3189 * no need to udpate the advertising data here.
3190 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003191 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003192 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003193
Johan Hedberg13928972013-03-15 17:07:00 -05003194 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003195 if (err < 0)
3196 mgmt_pending_remove(cmd);
3197
3198failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003199 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003200 return err;
3201}
3202
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003203static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003204 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003205{
Szymon Jancc35938b2011-03-22 13:12:21 +01003206 struct pending_cmd *cmd;
3207 int err;
3208
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003209 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003210
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003211 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003212
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003213 if (!hdev_is_powered(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_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003216 goto unlock;
3217 }
3218
Andre Guedes9a1a1992012-07-24 15:03:48 -03003219 if (!lmp_ssp_capable(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_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003222 goto unlock;
3223 }
3224
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003225 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003226 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003227 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003228 goto unlock;
3229 }
3230
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003231 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003232 if (!cmd) {
3233 err = -ENOMEM;
3234 goto unlock;
3235 }
3236
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003237 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3238 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3239 0, NULL);
3240 else
3241 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3242
Szymon Jancc35938b2011-03-22 13:12:21 +01003243 if (err < 0)
3244 mgmt_pending_remove(cmd);
3245
3246unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003247 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003248 return err;
3249}
3250
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003251static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003252 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003253{
Szymon Janc2763eda2011-03-22 13:12:22 +01003254 int err;
3255
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003256 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003257
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003258 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003259
Marcel Holtmannec109112014-01-10 02:07:30 -08003260 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3261 struct mgmt_cp_add_remote_oob_data *cp = data;
3262 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003263
Marcel Holtmannec109112014-01-10 02:07:30 -08003264 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3265 cp->hash, cp->randomizer);
3266 if (err < 0)
3267 status = MGMT_STATUS_FAILED;
3268 else
3269 status = MGMT_STATUS_SUCCESS;
3270
3271 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3272 status, &cp->addr, sizeof(cp->addr));
3273 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3274 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3275 u8 status;
3276
3277 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3278 cp->hash192,
3279 cp->randomizer192,
3280 cp->hash256,
3281 cp->randomizer256);
3282 if (err < 0)
3283 status = MGMT_STATUS_FAILED;
3284 else
3285 status = MGMT_STATUS_SUCCESS;
3286
3287 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3288 status, &cp->addr, sizeof(cp->addr));
3289 } else {
3290 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3291 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3292 MGMT_STATUS_INVALID_PARAMS);
3293 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003294
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003295 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003296 return err;
3297}
3298
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003299static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003300 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003301{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003302 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003303 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003304 int err;
3305
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003306 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003307
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003308 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003309
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003310 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003311 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003312 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003313 else
Szymon Janca6785be2012-12-13 15:11:21 +01003314 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003316 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003317 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003318
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003319 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003320 return err;
3321}
3322
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003323static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3324{
3325 struct pending_cmd *cmd;
3326 u8 type;
3327 int err;
3328
3329 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3330
3331 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3332 if (!cmd)
3333 return -ENOENT;
3334
3335 type = hdev->discovery.type;
3336
3337 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3338 &type, sizeof(type));
3339 mgmt_pending_remove(cmd);
3340
3341 return err;
3342}
3343
Andre Guedes7c307722013-04-30 15:29:28 -03003344static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3345{
3346 BT_DBG("status %d", status);
3347
3348 if (status) {
3349 hci_dev_lock(hdev);
3350 mgmt_start_discovery_failed(hdev, status);
3351 hci_dev_unlock(hdev);
3352 return;
3353 }
3354
3355 hci_dev_lock(hdev);
3356 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3357 hci_dev_unlock(hdev);
3358
3359 switch (hdev->discovery.type) {
3360 case DISCOV_TYPE_LE:
3361 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003362 DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003363 break;
3364
3365 case DISCOV_TYPE_INTERLEAVED:
3366 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003367 DISCOV_INTERLEAVED_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003368 break;
3369
3370 case DISCOV_TYPE_BREDR:
3371 break;
3372
3373 default:
3374 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3375 }
3376}
3377
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003378static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003379 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003380{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003381 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003382 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003383 struct hci_cp_le_set_scan_param param_cp;
3384 struct hci_cp_le_set_scan_enable enable_cp;
3385 struct hci_cp_inquiry inq_cp;
3386 struct hci_request req;
3387 /* General inquiry access code (GIAC) */
3388 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003389 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003390 int err;
3391
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003392 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003393
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003394 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003395
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003396 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003397 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003398 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003399 goto failed;
3400 }
3401
Andre Guedes642be6c2012-03-21 00:03:37 -03003402 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3403 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3404 MGMT_STATUS_BUSY);
3405 goto failed;
3406 }
3407
Johan Hedbergff9ef572012-01-04 14:23:45 +02003408 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003409 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003410 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003411 goto failed;
3412 }
3413
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003414 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003415 if (!cmd) {
3416 err = -ENOMEM;
3417 goto failed;
3418 }
3419
Andre Guedes4aab14e2012-02-17 20:39:36 -03003420 hdev->discovery.type = cp->type;
3421
Andre Guedes7c307722013-04-30 15:29:28 -03003422 hci_req_init(&req, hdev);
3423
Andre Guedes4aab14e2012-02-17 20:39:36 -03003424 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003425 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003426 status = mgmt_bredr_support(hdev);
3427 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003428 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003429 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003430 mgmt_pending_remove(cmd);
3431 goto failed;
3432 }
3433
Andre Guedes7c307722013-04-30 15:29:28 -03003434 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3435 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3436 MGMT_STATUS_BUSY);
3437 mgmt_pending_remove(cmd);
3438 goto failed;
3439 }
3440
3441 hci_inquiry_cache_flush(hdev);
3442
3443 memset(&inq_cp, 0, sizeof(inq_cp));
3444 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003445 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003446 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003447 break;
3448
3449 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003450 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003451 status = mgmt_le_support(hdev);
3452 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003453 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003454 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003455 mgmt_pending_remove(cmd);
3456 goto failed;
3457 }
3458
Andre Guedes7c307722013-04-30 15:29:28 -03003459 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003460 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003461 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3462 MGMT_STATUS_NOT_SUPPORTED);
3463 mgmt_pending_remove(cmd);
3464 goto failed;
3465 }
3466
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003467 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003468 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3469 MGMT_STATUS_REJECTED);
3470 mgmt_pending_remove(cmd);
3471 goto failed;
3472 }
3473
Andre Guedesc54c3862014-02-26 20:21:50 -03003474 /* If controller is scanning, it means the background scanning
3475 * is running. Thus, we should temporarily stop it in order to
3476 * set the discovery scanning parameters.
3477 */
3478 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3479 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003480
3481 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003482
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003483 /* All active scans will be done with either a resolvable
3484 * private address (when privacy feature has been enabled)
3485 * or unresolvable private address.
3486 */
3487 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003488 if (err < 0) {
3489 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3490 MGMT_STATUS_FAILED);
3491 mgmt_pending_remove(cmd);
3492 goto failed;
3493 }
3494
Andre Guedes7c307722013-04-30 15:29:28 -03003495 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003496 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3497 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003498 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003499 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3500 &param_cp);
3501
3502 memset(&enable_cp, 0, sizeof(enable_cp));
3503 enable_cp.enable = LE_SCAN_ENABLE;
3504 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3505 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3506 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003507 break;
3508
Andre Guedesf39799f2012-02-17 20:39:35 -03003509 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003510 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3511 MGMT_STATUS_INVALID_PARAMS);
3512 mgmt_pending_remove(cmd);
3513 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003514 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003515
Andre Guedes7c307722013-04-30 15:29:28 -03003516 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003517 if (err < 0)
3518 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003519 else
3520 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003521
3522failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003523 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003524 return err;
3525}
3526
Andre Guedes1183fdc2013-04-30 15:29:35 -03003527static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3528{
3529 struct pending_cmd *cmd;
3530 int err;
3531
3532 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3533 if (!cmd)
3534 return -ENOENT;
3535
3536 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3537 &hdev->discovery.type, sizeof(hdev->discovery.type));
3538 mgmt_pending_remove(cmd);
3539
3540 return err;
3541}
3542
Andre Guedes0e05bba2013-04-30 15:29:33 -03003543static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3544{
3545 BT_DBG("status %d", status);
3546
3547 hci_dev_lock(hdev);
3548
3549 if (status) {
3550 mgmt_stop_discovery_failed(hdev, status);
3551 goto unlock;
3552 }
3553
3554 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3555
3556unlock:
3557 hci_dev_unlock(hdev);
3558}
3559
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003560static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003561 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003562{
Johan Hedbergd9306502012-02-20 23:25:18 +02003563 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003564 struct pending_cmd *cmd;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003565 struct hci_cp_remote_name_req_cancel cp;
3566 struct inquiry_entry *e;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003567 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003568 int err;
3569
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003570 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003571
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003572 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003573
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003574 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003575 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003576 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3577 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003578 goto unlock;
3579 }
3580
3581 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003582 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003583 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3584 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003585 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003586 }
3587
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003588 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003589 if (!cmd) {
3590 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003591 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003592 }
3593
Andre Guedes0e05bba2013-04-30 15:29:33 -03003594 hci_req_init(&req, hdev);
3595
Andre Guedese0d9727e2012-03-20 15:15:36 -03003596 switch (hdev->discovery.state) {
3597 case DISCOVERY_FINDING:
Andre Guedes0e05bba2013-04-30 15:29:33 -03003598 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3599 hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
3600 } else {
3601 cancel_delayed_work(&hdev->le_scan_disable);
3602
Andre Guedesb1efcc22014-02-26 20:21:40 -03003603 hci_req_add_le_scan_disable(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003604 }
Andre Guedesc9ecc482012-03-15 16:52:08 -03003605
Andre Guedese0d9727e2012-03-20 15:15:36 -03003606 break;
3607
3608 case DISCOVERY_RESOLVING:
3609 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003610 NAME_PENDING);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003611 if (!e) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003612 mgmt_pending_remove(cmd);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003613 err = cmd_complete(sk, hdev->id,
3614 MGMT_OP_STOP_DISCOVERY, 0,
3615 &mgmt_cp->type,
3616 sizeof(mgmt_cp->type));
3617 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3618 goto unlock;
3619 }
3620
3621 bacpy(&cp.bdaddr, &e->data.bdaddr);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003622 hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
3623 &cp);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003624
3625 break;
3626
3627 default:
3628 BT_DBG("unknown discovery state %u", hdev->discovery.state);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003629
3630 mgmt_pending_remove(cmd);
3631 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
3632 MGMT_STATUS_FAILED, &mgmt_cp->type,
3633 sizeof(mgmt_cp->type));
3634 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003635 }
3636
Andre Guedes0e05bba2013-04-30 15:29:33 -03003637 err = hci_req_run(&req, stop_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003638 if (err < 0)
3639 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003640 else
3641 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003642
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003643unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003644 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003645 return err;
3646}
3647
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003648static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003649 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003650{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003651 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003652 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003653 int err;
3654
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003655 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003656
Johan Hedberg561aafb2012-01-04 13:31:59 +02003657 hci_dev_lock(hdev);
3658
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003659 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003660 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3661 MGMT_STATUS_FAILED, &cp->addr,
3662 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003663 goto failed;
3664 }
3665
Johan Hedberga198e7b2012-02-17 14:27:06 +02003666 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003667 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003668 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3669 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3670 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003671 goto failed;
3672 }
3673
3674 if (cp->name_known) {
3675 e->name_state = NAME_KNOWN;
3676 list_del(&e->list);
3677 } else {
3678 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003679 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003680 }
3681
Johan Hedberge3846622013-01-09 15:29:33 +02003682 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3683 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003684
3685failed:
3686 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003687 return err;
3688}
3689
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003690static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003691 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003692{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003693 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003694 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003695 int err;
3696
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003697 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003698
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003699 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003700 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3701 MGMT_STATUS_INVALID_PARAMS,
3702 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003703
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003704 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003705
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003706 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003707 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003708 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003709 else
Szymon Janca6785be2012-12-13 15:11:21 +01003710 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003711
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003712 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003713 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003714
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003715 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003716
3717 return err;
3718}
3719
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003720static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003721 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003722{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003723 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003724 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003725 int err;
3726
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003727 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003728
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003729 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003730 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3731 MGMT_STATUS_INVALID_PARAMS,
3732 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003733
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003734 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003735
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003736 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003737 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003738 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003739 else
Szymon Janca6785be2012-12-13 15:11:21 +01003740 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003741
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003742 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003743 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003744
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003745 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003746
3747 return err;
3748}
3749
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003750static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3751 u16 len)
3752{
3753 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003754 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003755 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003756 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003757
3758 BT_DBG("%s", hdev->name);
3759
Szymon Jancc72d4b82012-03-16 16:02:57 +01003760 source = __le16_to_cpu(cp->source);
3761
3762 if (source > 0x0002)
3763 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3764 MGMT_STATUS_INVALID_PARAMS);
3765
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003766 hci_dev_lock(hdev);
3767
Szymon Jancc72d4b82012-03-16 16:02:57 +01003768 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003769 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3770 hdev->devid_product = __le16_to_cpu(cp->product);
3771 hdev->devid_version = __le16_to_cpu(cp->version);
3772
3773 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3774
Johan Hedberg890ea892013-03-15 17:06:52 -05003775 hci_req_init(&req, hdev);
3776 update_eir(&req);
3777 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003778
3779 hci_dev_unlock(hdev);
3780
3781 return err;
3782}
3783
Johan Hedberg4375f102013-09-25 13:26:10 +03003784static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3785{
3786 struct cmd_lookup match = { NULL, hdev };
3787
3788 if (status) {
3789 u8 mgmt_err = mgmt_status(status);
3790
3791 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3792 cmd_status_rsp, &mgmt_err);
3793 return;
3794 }
3795
3796 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3797 &match);
3798
3799 new_settings(hdev, match.sk);
3800
3801 if (match.sk)
3802 sock_put(match.sk);
3803}
3804
Marcel Holtmann21b51872013-10-10 09:47:53 -07003805static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3806 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003807{
3808 struct mgmt_mode *cp = data;
3809 struct pending_cmd *cmd;
3810 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003811 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003812 int err;
3813
3814 BT_DBG("request for %s", hdev->name);
3815
Johan Hedberge6fe7982013-10-02 15:45:22 +03003816 status = mgmt_le_support(hdev);
3817 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003818 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003819 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003820
3821 if (cp->val != 0x00 && cp->val != 0x01)
3822 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3823 MGMT_STATUS_INVALID_PARAMS);
3824
3825 hci_dev_lock(hdev);
3826
3827 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003828 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003829
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003830 /* The following conditions are ones which mean that we should
3831 * not do any HCI communication but directly send a mgmt
3832 * response to user space (after toggling the flag if
3833 * necessary).
3834 */
3835 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003836 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003837 bool changed = false;
3838
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003839 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3840 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003841 changed = true;
3842 }
3843
3844 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3845 if (err < 0)
3846 goto unlock;
3847
3848 if (changed)
3849 err = new_settings(hdev, sk);
3850
3851 goto unlock;
3852 }
3853
3854 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3855 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3856 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3857 MGMT_STATUS_BUSY);
3858 goto unlock;
3859 }
3860
3861 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3862 if (!cmd) {
3863 err = -ENOMEM;
3864 goto unlock;
3865 }
3866
3867 hci_req_init(&req, hdev);
3868
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003869 if (val)
3870 enable_advertising(&req);
3871 else
3872 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003873
3874 err = hci_req_run(&req, set_advertising_complete);
3875 if (err < 0)
3876 mgmt_pending_remove(cmd);
3877
3878unlock:
3879 hci_dev_unlock(hdev);
3880 return err;
3881}
3882
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003883static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3884 void *data, u16 len)
3885{
3886 struct mgmt_cp_set_static_address *cp = data;
3887 int err;
3888
3889 BT_DBG("%s", hdev->name);
3890
Marcel Holtmann62af4442013-10-02 22:10:32 -07003891 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003892 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003893 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003894
3895 if (hdev_is_powered(hdev))
3896 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3897 MGMT_STATUS_REJECTED);
3898
3899 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3900 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3901 return cmd_status(sk, hdev->id,
3902 MGMT_OP_SET_STATIC_ADDRESS,
3903 MGMT_STATUS_INVALID_PARAMS);
3904
3905 /* Two most significant bits shall be set */
3906 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3907 return cmd_status(sk, hdev->id,
3908 MGMT_OP_SET_STATIC_ADDRESS,
3909 MGMT_STATUS_INVALID_PARAMS);
3910 }
3911
3912 hci_dev_lock(hdev);
3913
3914 bacpy(&hdev->static_addr, &cp->bdaddr);
3915
3916 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3917
3918 hci_dev_unlock(hdev);
3919
3920 return err;
3921}
3922
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003923static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3924 void *data, u16 len)
3925{
3926 struct mgmt_cp_set_scan_params *cp = data;
3927 __u16 interval, window;
3928 int err;
3929
3930 BT_DBG("%s", hdev->name);
3931
3932 if (!lmp_le_capable(hdev))
3933 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3934 MGMT_STATUS_NOT_SUPPORTED);
3935
3936 interval = __le16_to_cpu(cp->interval);
3937
3938 if (interval < 0x0004 || interval > 0x4000)
3939 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3940 MGMT_STATUS_INVALID_PARAMS);
3941
3942 window = __le16_to_cpu(cp->window);
3943
3944 if (window < 0x0004 || window > 0x4000)
3945 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3946 MGMT_STATUS_INVALID_PARAMS);
3947
Marcel Holtmann899e1072013-10-14 09:55:32 -07003948 if (window > interval)
3949 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3950 MGMT_STATUS_INVALID_PARAMS);
3951
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003952 hci_dev_lock(hdev);
3953
3954 hdev->le_scan_interval = interval;
3955 hdev->le_scan_window = window;
3956
3957 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3958
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003959 /* If background scan is running, restart it so new parameters are
3960 * loaded.
3961 */
3962 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
3963 hdev->discovery.state == DISCOVERY_STOPPED) {
3964 struct hci_request req;
3965
3966 hci_req_init(&req, hdev);
3967
3968 hci_req_add_le_scan_disable(&req);
3969 hci_req_add_le_passive_scan(&req);
3970
3971 hci_req_run(&req, NULL);
3972 }
3973
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003974 hci_dev_unlock(hdev);
3975
3976 return err;
3977}
3978
Johan Hedberg33e38b32013-03-15 17:07:05 -05003979static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3980{
3981 struct pending_cmd *cmd;
3982
3983 BT_DBG("status 0x%02x", status);
3984
3985 hci_dev_lock(hdev);
3986
3987 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3988 if (!cmd)
3989 goto unlock;
3990
3991 if (status) {
3992 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3993 mgmt_status(status));
3994 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05003995 struct mgmt_mode *cp = cmd->param;
3996
3997 if (cp->val)
3998 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
3999 else
4000 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4001
Johan Hedberg33e38b32013-03-15 17:07:05 -05004002 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4003 new_settings(hdev, cmd->sk);
4004 }
4005
4006 mgmt_pending_remove(cmd);
4007
4008unlock:
4009 hci_dev_unlock(hdev);
4010}
4011
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004012static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004013 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004014{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004015 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004016 struct pending_cmd *cmd;
4017 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004018 int err;
4019
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004020 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004021
Johan Hedberg56f87902013-10-02 13:43:13 +03004022 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4023 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004024 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4025 MGMT_STATUS_NOT_SUPPORTED);
4026
Johan Hedberga7e80f22013-01-09 16:05:19 +02004027 if (cp->val != 0x00 && cp->val != 0x01)
4028 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4029 MGMT_STATUS_INVALID_PARAMS);
4030
Johan Hedberg5400c042012-02-21 16:40:33 +02004031 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004032 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004033 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004034
4035 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004036 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004037 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004038
4039 hci_dev_lock(hdev);
4040
Johan Hedberg05cbf292013-03-15 17:07:07 -05004041 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4042 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4043 MGMT_STATUS_BUSY);
4044 goto unlock;
4045 }
4046
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004047 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4048 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4049 hdev);
4050 goto unlock;
4051 }
4052
Johan Hedberg33e38b32013-03-15 17:07:05 -05004053 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4054 data, len);
4055 if (!cmd) {
4056 err = -ENOMEM;
4057 goto unlock;
4058 }
4059
4060 hci_req_init(&req, hdev);
4061
Johan Hedberg406d7802013-03-15 17:07:09 -05004062 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004063
4064 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004065 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004066 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004067 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004068 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004069 }
4070
Johan Hedberg33e38b32013-03-15 17:07:05 -05004071unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004072 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004073
Antti Julkuf6422ec2011-06-22 13:11:56 +03004074 return err;
4075}
4076
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004077static void set_bredr_scan(struct hci_request *req)
4078{
4079 struct hci_dev *hdev = req->hdev;
4080 u8 scan = 0;
4081
4082 /* Ensure that fast connectable is disabled. This function will
4083 * not do anything if the page scan parameters are already what
4084 * they should be.
4085 */
4086 write_fast_connectable(req, false);
4087
4088 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4089 scan |= SCAN_PAGE;
4090 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4091 scan |= SCAN_INQUIRY;
4092
4093 if (scan)
4094 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4095}
4096
Johan Hedberg0663ca22013-10-02 13:43:14 +03004097static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4098{
4099 struct pending_cmd *cmd;
4100
4101 BT_DBG("status 0x%02x", status);
4102
4103 hci_dev_lock(hdev);
4104
4105 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4106 if (!cmd)
4107 goto unlock;
4108
4109 if (status) {
4110 u8 mgmt_err = mgmt_status(status);
4111
4112 /* We need to restore the flag if related HCI commands
4113 * failed.
4114 */
4115 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4116
4117 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4118 } else {
4119 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4120 new_settings(hdev, cmd->sk);
4121 }
4122
4123 mgmt_pending_remove(cmd);
4124
4125unlock:
4126 hci_dev_unlock(hdev);
4127}
4128
4129static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4130{
4131 struct mgmt_mode *cp = data;
4132 struct pending_cmd *cmd;
4133 struct hci_request req;
4134 int err;
4135
4136 BT_DBG("request for %s", hdev->name);
4137
4138 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4139 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4140 MGMT_STATUS_NOT_SUPPORTED);
4141
4142 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4143 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4144 MGMT_STATUS_REJECTED);
4145
4146 if (cp->val != 0x00 && cp->val != 0x01)
4147 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4148 MGMT_STATUS_INVALID_PARAMS);
4149
4150 hci_dev_lock(hdev);
4151
4152 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4153 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4154 goto unlock;
4155 }
4156
4157 if (!hdev_is_powered(hdev)) {
4158 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004159 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4160 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4161 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4162 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4163 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4164 }
4165
4166 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4167
4168 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4169 if (err < 0)
4170 goto unlock;
4171
4172 err = new_settings(hdev, sk);
4173 goto unlock;
4174 }
4175
4176 /* Reject disabling when powered on */
4177 if (!cp->val) {
4178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4179 MGMT_STATUS_REJECTED);
4180 goto unlock;
4181 }
4182
4183 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4184 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4185 MGMT_STATUS_BUSY);
4186 goto unlock;
4187 }
4188
4189 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4190 if (!cmd) {
4191 err = -ENOMEM;
4192 goto unlock;
4193 }
4194
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004195 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004196 * generates the correct flags.
4197 */
4198 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4199
4200 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004201
4202 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4203 set_bredr_scan(&req);
4204
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004205 /* Since only the advertising data flags will change, there
4206 * is no need to update the scan response data.
4207 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004208 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004209
Johan Hedberg0663ca22013-10-02 13:43:14 +03004210 err = hci_req_run(&req, set_bredr_complete);
4211 if (err < 0)
4212 mgmt_pending_remove(cmd);
4213
4214unlock:
4215 hci_dev_unlock(hdev);
4216 return err;
4217}
4218
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004219static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4220 void *data, u16 len)
4221{
4222 struct mgmt_mode *cp = data;
4223 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004224 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004225 int err;
4226
4227 BT_DBG("request for %s", hdev->name);
4228
4229 status = mgmt_bredr_support(hdev);
4230 if (status)
4231 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4232 status);
4233
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004234 if (!lmp_sc_capable(hdev) &&
4235 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004236 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4237 MGMT_STATUS_NOT_SUPPORTED);
4238
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004239 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004240 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4241 MGMT_STATUS_INVALID_PARAMS);
4242
4243 hci_dev_lock(hdev);
4244
4245 if (!hdev_is_powered(hdev)) {
4246 bool changed;
4247
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004248 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004249 changed = !test_and_set_bit(HCI_SC_ENABLED,
4250 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004251 if (cp->val == 0x02)
4252 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4253 else
4254 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4255 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004256 changed = test_and_clear_bit(HCI_SC_ENABLED,
4257 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004258 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4259 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004260
4261 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4262 if (err < 0)
4263 goto failed;
4264
4265 if (changed)
4266 err = new_settings(hdev, sk);
4267
4268 goto failed;
4269 }
4270
4271 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4272 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4273 MGMT_STATUS_BUSY);
4274 goto failed;
4275 }
4276
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004277 val = !!cp->val;
4278
4279 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4280 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004281 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4282 goto failed;
4283 }
4284
4285 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4286 if (!cmd) {
4287 err = -ENOMEM;
4288 goto failed;
4289 }
4290
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004291 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004292 if (err < 0) {
4293 mgmt_pending_remove(cmd);
4294 goto failed;
4295 }
4296
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004297 if (cp->val == 0x02)
4298 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4299 else
4300 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4301
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004302failed:
4303 hci_dev_unlock(hdev);
4304 return err;
4305}
4306
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004307static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4308 void *data, u16 len)
4309{
4310 struct mgmt_mode *cp = data;
4311 bool changed;
4312 int err;
4313
4314 BT_DBG("request for %s", hdev->name);
4315
4316 if (cp->val != 0x00 && cp->val != 0x01)
4317 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4318 MGMT_STATUS_INVALID_PARAMS);
4319
4320 hci_dev_lock(hdev);
4321
4322 if (cp->val)
4323 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4324 else
4325 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4326
4327 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4328 if (err < 0)
4329 goto unlock;
4330
4331 if (changed)
4332 err = new_settings(hdev, sk);
4333
4334unlock:
4335 hci_dev_unlock(hdev);
4336 return err;
4337}
4338
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004339static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4340 u16 len)
4341{
4342 struct mgmt_cp_set_privacy *cp = cp_data;
4343 bool changed;
4344 int err;
4345
4346 BT_DBG("request for %s", hdev->name);
4347
4348 if (!lmp_le_capable(hdev))
4349 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4350 MGMT_STATUS_NOT_SUPPORTED);
4351
4352 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4353 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4354 MGMT_STATUS_INVALID_PARAMS);
4355
4356 if (hdev_is_powered(hdev))
4357 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4358 MGMT_STATUS_REJECTED);
4359
4360 hci_dev_lock(hdev);
4361
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004362 /* If user space supports this command it is also expected to
4363 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4364 */
4365 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4366
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004367 if (cp->privacy) {
4368 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4369 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4370 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4371 } else {
4372 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4373 memset(hdev->irk, 0, sizeof(hdev->irk));
4374 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4375 }
4376
4377 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4378 if (err < 0)
4379 goto unlock;
4380
4381 if (changed)
4382 err = new_settings(hdev, sk);
4383
4384unlock:
4385 hci_dev_unlock(hdev);
4386 return err;
4387}
4388
Johan Hedberg41edf162014-02-18 10:19:35 +02004389static bool irk_is_valid(struct mgmt_irk_info *irk)
4390{
4391 switch (irk->addr.type) {
4392 case BDADDR_LE_PUBLIC:
4393 return true;
4394
4395 case BDADDR_LE_RANDOM:
4396 /* Two most significant bits shall be set */
4397 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4398 return false;
4399 return true;
4400 }
4401
4402 return false;
4403}
4404
4405static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4406 u16 len)
4407{
4408 struct mgmt_cp_load_irks *cp = cp_data;
4409 u16 irk_count, expected_len;
4410 int i, err;
4411
4412 BT_DBG("request for %s", hdev->name);
4413
4414 if (!lmp_le_capable(hdev))
4415 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4416 MGMT_STATUS_NOT_SUPPORTED);
4417
4418 irk_count = __le16_to_cpu(cp->irk_count);
4419
4420 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4421 if (expected_len != len) {
4422 BT_ERR("load_irks: expected %u bytes, got %u bytes",
4423 len, expected_len);
4424 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4425 MGMT_STATUS_INVALID_PARAMS);
4426 }
4427
4428 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4429
4430 for (i = 0; i < irk_count; i++) {
4431 struct mgmt_irk_info *key = &cp->irks[i];
4432
4433 if (!irk_is_valid(key))
4434 return cmd_status(sk, hdev->id,
4435 MGMT_OP_LOAD_IRKS,
4436 MGMT_STATUS_INVALID_PARAMS);
4437 }
4438
4439 hci_dev_lock(hdev);
4440
4441 hci_smp_irks_clear(hdev);
4442
4443 for (i = 0; i < irk_count; i++) {
4444 struct mgmt_irk_info *irk = &cp->irks[i];
4445 u8 addr_type;
4446
4447 if (irk->addr.type == BDADDR_LE_PUBLIC)
4448 addr_type = ADDR_LE_DEV_PUBLIC;
4449 else
4450 addr_type = ADDR_LE_DEV_RANDOM;
4451
4452 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4453 BDADDR_ANY);
4454 }
4455
4456 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4457
4458 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4459
4460 hci_dev_unlock(hdev);
4461
4462 return err;
4463}
4464
Johan Hedberg3f706b72013-01-20 14:27:16 +02004465static bool ltk_is_valid(struct mgmt_ltk_info *key)
4466{
4467 if (key->master != 0x00 && key->master != 0x01)
4468 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004469
4470 switch (key->addr.type) {
4471 case BDADDR_LE_PUBLIC:
4472 return true;
4473
4474 case BDADDR_LE_RANDOM:
4475 /* Two most significant bits shall be set */
4476 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4477 return false;
4478 return true;
4479 }
4480
4481 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004482}
4483
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004484static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004485 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004486{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004487 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4488 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004489 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004490
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004491 BT_DBG("request for %s", hdev->name);
4492
4493 if (!lmp_le_capable(hdev))
4494 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4495 MGMT_STATUS_NOT_SUPPORTED);
4496
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004497 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004498
4499 expected_len = sizeof(*cp) + key_count *
4500 sizeof(struct mgmt_ltk_info);
4501 if (expected_len != len) {
4502 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004503 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004504 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004505 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004506 }
4507
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004508 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004509
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004510 for (i = 0; i < key_count; i++) {
4511 struct mgmt_ltk_info *key = &cp->keys[i];
4512
Johan Hedberg3f706b72013-01-20 14:27:16 +02004513 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004514 return cmd_status(sk, hdev->id,
4515 MGMT_OP_LOAD_LONG_TERM_KEYS,
4516 MGMT_STATUS_INVALID_PARAMS);
4517 }
4518
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004519 hci_dev_lock(hdev);
4520
4521 hci_smp_ltks_clear(hdev);
4522
4523 for (i = 0; i < key_count; i++) {
4524 struct mgmt_ltk_info *key = &cp->keys[i];
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004525 u8 type, addr_type;
4526
4527 if (key->addr.type == BDADDR_LE_PUBLIC)
4528 addr_type = ADDR_LE_DEV_PUBLIC;
4529 else
4530 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004531
4532 if (key->master)
4533 type = HCI_SMP_LTK;
4534 else
4535 type = HCI_SMP_LTK_SLAVE;
4536
Johan Hedberg35d70272014-02-19 14:57:47 +02004537 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
4538 key->type, key->val, key->enc_size, key->ediv,
4539 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004540 }
4541
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004542 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4543 NULL, 0);
4544
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004545 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004546
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004547 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004548}
4549
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004550static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004551 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4552 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004553 bool var_len;
4554 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004555} mgmt_handlers[] = {
4556 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004557 { read_version, false, MGMT_READ_VERSION_SIZE },
4558 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4559 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4560 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4561 { set_powered, false, MGMT_SETTING_SIZE },
4562 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4563 { set_connectable, false, MGMT_SETTING_SIZE },
4564 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4565 { set_pairable, false, MGMT_SETTING_SIZE },
4566 { set_link_security, false, MGMT_SETTING_SIZE },
4567 { set_ssp, false, MGMT_SETTING_SIZE },
4568 { set_hs, false, MGMT_SETTING_SIZE },
4569 { set_le, false, MGMT_SETTING_SIZE },
4570 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4571 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4572 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4573 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4574 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4575 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4576 { disconnect, false, MGMT_DISCONNECT_SIZE },
4577 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4578 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4579 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4580 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4581 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4582 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4583 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4584 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4585 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4586 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4587 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4588 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004589 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004590 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4591 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4592 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4593 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4594 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4595 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004596 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004597 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004598 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004599 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004600 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004601 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004602 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004603 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004604 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004605};
4606
4607
Johan Hedberg03811012010-12-08 00:21:06 +02004608int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4609{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004610 void *buf;
4611 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004612 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004613 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004614 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004615 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004616 int err;
4617
4618 BT_DBG("got %zu bytes", msglen);
4619
4620 if (msglen < sizeof(*hdr))
4621 return -EINVAL;
4622
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004623 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004624 if (!buf)
4625 return -ENOMEM;
4626
4627 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4628 err = -EFAULT;
4629 goto done;
4630 }
4631
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004632 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004633 opcode = __le16_to_cpu(hdr->opcode);
4634 index = __le16_to_cpu(hdr->index);
4635 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004636
4637 if (len != msglen - sizeof(*hdr)) {
4638 err = -EINVAL;
4639 goto done;
4640 }
4641
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004642 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004643 hdev = hci_dev_get(index);
4644 if (!hdev) {
4645 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004646 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004647 goto done;
4648 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004649
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004650 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4651 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004652 err = cmd_status(sk, index, opcode,
4653 MGMT_STATUS_INVALID_INDEX);
4654 goto done;
4655 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004656 }
4657
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004658 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004659 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004660 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004661 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004662 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004663 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004664 }
4665
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004666 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004667 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004668 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004669 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004670 goto done;
4671 }
4672
Johan Hedbergbe22b542012-03-01 22:24:41 +02004673 handler = &mgmt_handlers[opcode];
4674
4675 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004676 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004677 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004678 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004679 goto done;
4680 }
4681
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004682 if (hdev)
4683 mgmt_init_hdev(sk, hdev);
4684
4685 cp = buf + sizeof(*hdr);
4686
Johan Hedbergbe22b542012-03-01 22:24:41 +02004687 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004688 if (err < 0)
4689 goto done;
4690
Johan Hedberg03811012010-12-08 00:21:06 +02004691 err = msglen;
4692
4693done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004694 if (hdev)
4695 hci_dev_put(hdev);
4696
Johan Hedberg03811012010-12-08 00:21:06 +02004697 kfree(buf);
4698 return err;
4699}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004700
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004701void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004702{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004703 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004704 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004705
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004706 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004707}
4708
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004709void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004710{
Johan Hedberg5f159032012-03-02 03:13:19 +02004711 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004712
Marcel Holtmann1514b892013-10-06 08:25:01 -07004713 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004714 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004715
Johan Hedberg744cf192011-11-08 20:40:14 +02004716 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004717
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004718 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004719}
4720
Andre Guedes6046dc32014-02-26 20:21:51 -03004721/* This function requires the caller holds hdev->lock */
4722static void restart_le_auto_conns(struct hci_dev *hdev)
4723{
4724 struct hci_conn_params *p;
4725
4726 list_for_each_entry(p, &hdev->le_conn_params, list) {
4727 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4728 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4729 }
4730}
4731
Johan Hedberg229ab392013-03-15 17:06:53 -05004732static void powered_complete(struct hci_dev *hdev, u8 status)
4733{
4734 struct cmd_lookup match = { NULL, hdev };
4735
4736 BT_DBG("status 0x%02x", status);
4737
4738 hci_dev_lock(hdev);
4739
Andre Guedes6046dc32014-02-26 20:21:51 -03004740 restart_le_auto_conns(hdev);
4741
Johan Hedberg229ab392013-03-15 17:06:53 -05004742 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4743
4744 new_settings(hdev, match.sk);
4745
4746 hci_dev_unlock(hdev);
4747
4748 if (match.sk)
4749 sock_put(match.sk);
4750}
4751
Johan Hedberg70da6242013-03-15 17:06:51 -05004752static int powered_update_hci(struct hci_dev *hdev)
4753{
Johan Hedberg890ea892013-03-15 17:06:52 -05004754 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004755 u8 link_sec;
4756
Johan Hedberg890ea892013-03-15 17:06:52 -05004757 hci_req_init(&req, hdev);
4758
Johan Hedberg70da6242013-03-15 17:06:51 -05004759 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4760 !lmp_host_ssp_capable(hdev)) {
4761 u8 ssp = 1;
4762
Johan Hedberg890ea892013-03-15 17:06:52 -05004763 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004764 }
4765
Johan Hedbergc73eee92013-04-19 18:35:21 +03004766 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4767 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05004768 struct hci_cp_write_le_host_supported cp;
4769
4770 cp.le = 1;
4771 cp.simul = lmp_le_br_capable(hdev);
4772
4773 /* Check first if we already have the right
4774 * host state (host features set)
4775 */
4776 if (cp.le != lmp_host_le_capable(hdev) ||
4777 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05004778 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
4779 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004780 }
4781
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004782 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004783 /* Make sure the controller has a good default for
4784 * advertising data. This also applies to the case
4785 * where BR/EDR was toggled during the AUTO_OFF phase.
4786 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004787 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004788 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004789 update_scan_rsp_data(&req);
4790 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004791
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004792 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
4793 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03004794 }
4795
Johan Hedberg70da6242013-03-15 17:06:51 -05004796 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4797 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05004798 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
4799 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05004800
4801 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03004802 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
4803 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004804 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05004805 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004806 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05004807 }
4808
Johan Hedberg229ab392013-03-15 17:06:53 -05004809 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05004810}
4811
Johan Hedberg744cf192011-11-08 20:40:14 +02004812int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02004813{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02004814 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05004815 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
4816 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004817 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004818
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004819 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
4820 return 0;
4821
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004822 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05004823 if (powered_update_hci(hdev) == 0)
4824 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02004825
Johan Hedberg229ab392013-03-15 17:06:53 -05004826 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
4827 &match);
4828 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004829 }
4830
Johan Hedberg229ab392013-03-15 17:06:53 -05004831 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4832 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
4833
4834 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
4835 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
4836 zero_cod, sizeof(zero_cod), NULL);
4837
4838new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004839 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004840
4841 if (match.sk)
4842 sock_put(match.sk);
4843
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004844 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004845}
Johan Hedberg73f22f62010-12-29 16:00:25 +02004846
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004847void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03004848{
4849 struct pending_cmd *cmd;
4850 u8 status;
4851
4852 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
4853 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004854 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03004855
4856 if (err == -ERFKILL)
4857 status = MGMT_STATUS_RFKILLED;
4858 else
4859 status = MGMT_STATUS_FAILED;
4860
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004861 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004862
4863 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004864}
4865
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004866void mgmt_discoverable_timeout(struct hci_dev *hdev)
4867{
4868 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004869
4870 hci_dev_lock(hdev);
4871
4872 /* When discoverable timeout triggers, then just make sure
4873 * the limited discoverable flag is cleared. Even in the case
4874 * of a timeout triggered from general discoverable, it is
4875 * safe to unconditionally clear the flag.
4876 */
4877 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004878 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004879
4880 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03004881 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4882 u8 scan = SCAN_PAGE;
4883 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
4884 sizeof(scan), &scan);
4885 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004886 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004887 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004888 hci_req_run(&req, NULL);
4889
4890 hdev->discov_timeout = 0;
4891
Johan Hedberg9a43e252013-10-20 19:00:07 +03004892 new_settings(hdev, NULL);
4893
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004894 hci_dev_unlock(hdev);
4895}
4896
Marcel Holtmann86a75642013-10-15 06:33:54 -07004897void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02004898{
Marcel Holtmann86a75642013-10-15 06:33:54 -07004899 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02004900
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004901 /* Nothing needed here if there's a pending command since that
4902 * commands request completion callback takes care of everything
4903 * necessary.
4904 */
4905 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07004906 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004907
Johan Hedbergbd107992014-02-24 14:52:19 +02004908 /* Powering off may clear the scan mode - don't let that interfere */
4909 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4910 return;
4911
Johan Hedberg9a43e252013-10-20 19:00:07 +03004912 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07004913 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004914 } else {
4915 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07004916 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004917 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004918
Johan Hedberg9a43e252013-10-20 19:00:07 +03004919 if (changed) {
4920 struct hci_request req;
4921
4922 /* In case this change in discoverable was triggered by
4923 * a disabling of connectable there could be a need to
4924 * update the advertising flags.
4925 */
4926 hci_req_init(&req, hdev);
4927 update_adv_data(&req);
4928 hci_req_run(&req, NULL);
4929
Marcel Holtmann86a75642013-10-15 06:33:54 -07004930 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004931 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004932}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004933
Marcel Holtmanna3309162013-10-15 06:33:55 -07004934void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004935{
Marcel Holtmanna3309162013-10-15 06:33:55 -07004936 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004937
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004938 /* Nothing needed here if there's a pending command since that
4939 * commands request completion callback takes care of everything
4940 * necessary.
4941 */
4942 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07004943 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004944
Johan Hedbergce3f24c2014-02-24 14:52:20 +02004945 /* Powering off may clear the scan mode - don't let that interfere */
4946 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4947 return;
4948
Marcel Holtmanna3309162013-10-15 06:33:55 -07004949 if (connectable)
4950 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
4951 else
4952 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004953
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004954 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07004955 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004956}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004957
Johan Hedberg778b2352014-02-24 14:52:17 +02004958void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
4959{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02004960 /* Powering off may stop advertising - don't let that interfere */
4961 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4962 return;
4963
Johan Hedberg778b2352014-02-24 14:52:17 +02004964 if (advertising)
4965 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4966 else
4967 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4968}
4969
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07004970void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004971{
Johan Hedbergca69b792011-11-11 18:10:00 +02004972 u8 mgmt_err = mgmt_status(status);
4973
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004974 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02004975 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004976 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004977
4978 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02004979 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004980 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004981}
4982
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004983void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
4984 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004985{
Johan Hedberg86742e12011-11-07 23:13:38 +02004986 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004987
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004988 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004989
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004990 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02004991 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03004992 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004993 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03004994 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004995 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004996
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004997 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004998}
Johan Hedbergf7520542011-01-20 12:34:39 +02004999
Johan Hedbergba74b662014-02-19 14:57:45 +02005000void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005001{
5002 struct mgmt_ev_new_long_term_key ev;
5003
5004 memset(&ev, 0, sizeof(ev));
5005
Marcel Holtmann5192d302014-02-19 17:11:58 -08005006 /* Devices using resolvable or non-resolvable random addresses
5007 * without providing an indentity resolving key don't require
5008 * to store long term keys. Their addresses will change the
5009 * next time around.
5010 *
5011 * Only when a remote device provides an identity address
5012 * make sure the long term key is stored. If the remote
5013 * identity is known, the long term keys are internally
5014 * mapped to the identity address. So allow static random
5015 * and public addresses here.
5016 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005017 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5018 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5019 ev.store_hint = 0x00;
5020 else
5021 ev.store_hint = 0x01;
5022
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005023 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005024 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Marcel Holtmannd40f3ee2014-01-31 18:42:17 -08005025 ev.key.type = key->authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005026 ev.key.enc_size = key->enc_size;
5027 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005028 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005029
5030 if (key->type == HCI_SMP_LTK)
5031 ev.key.master = 1;
5032
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005033 memcpy(ev.key.val, key->val, sizeof(key->val));
5034
Marcel Holtmann083368f2013-10-15 14:26:29 -07005035 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005036}
5037
Johan Hedberg95fbac82014-02-19 15:18:31 +02005038void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5039{
5040 struct mgmt_ev_new_irk ev;
5041
5042 memset(&ev, 0, sizeof(ev));
5043
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005044 /* For identity resolving keys from devices that are already
5045 * using a public address or static random address, do not
5046 * ask for storing this key. The identity resolving key really
5047 * is only mandatory for devices using resovlable random
5048 * addresses.
5049 *
5050 * Storing all identity resolving keys has the downside that
5051 * they will be also loaded on next boot of they system. More
5052 * identity resolving keys, means more time during scanning is
5053 * needed to actually resolve these addresses.
5054 */
5055 if (bacmp(&irk->rpa, BDADDR_ANY))
5056 ev.store_hint = 0x01;
5057 else
5058 ev.store_hint = 0x00;
5059
Johan Hedberg95fbac82014-02-19 15:18:31 +02005060 bacpy(&ev.rpa, &irk->rpa);
5061 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5062 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5063 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5064
5065 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5066}
5067
Marcel Holtmann94933992013-10-15 10:26:39 -07005068static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5069 u8 data_len)
5070{
5071 eir[eir_len++] = sizeof(type) + data_len;
5072 eir[eir_len++] = type;
5073 memcpy(&eir[eir_len], data, data_len);
5074 eir_len += data_len;
5075
5076 return eir_len;
5077}
5078
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005079void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5080 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5081 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005082{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005083 char buf[512];
5084 struct mgmt_ev_device_connected *ev = (void *) buf;
5085 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005086
Johan Hedbergb644ba32012-01-17 21:48:47 +02005087 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005088 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005089
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005090 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005091
Johan Hedbergb644ba32012-01-17 21:48:47 +02005092 if (name_len > 0)
5093 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005094 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005095
5096 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005097 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005098 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005099
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005100 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005101
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005102 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5103 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005104}
5105
Johan Hedberg8962ee72011-01-20 12:40:27 +02005106static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5107{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005108 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005109 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005110 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005111
Johan Hedberg88c3df12012-02-09 14:27:38 +02005112 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5113 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005114
Johan Hedbergaee9b212012-02-18 15:07:59 +02005115 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005116 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005117
5118 *sk = cmd->sk;
5119 sock_hold(*sk);
5120
Johan Hedberga664b5b2011-02-19 12:06:02 -03005121 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005122}
5123
Johan Hedberg124f6e32012-02-09 13:50:12 +02005124static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005125{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005126 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005127 struct mgmt_cp_unpair_device *cp = cmd->param;
5128 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005129
5130 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005131 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5132 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005133
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005134 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5135
Johan Hedbergaee9b212012-02-18 15:07:59 +02005136 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005137
5138 mgmt_pending_remove(cmd);
5139}
5140
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005141void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005142 u8 link_type, u8 addr_type, u8 reason,
5143 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005144{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005145 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005146 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005147 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005148
Johan Hedberg8b064a32014-02-24 14:52:22 +02005149 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5150 if (power_off) {
5151 struct mgmt_mode *cp = power_off->param;
5152
5153 /* The connection is still in hci_conn_hash so test for 1
5154 * instead of 0 to know if this is the last one.
5155 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005156 if (!cp->val && hci_conn_count(hdev) == 1) {
5157 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005158 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005159 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005160 }
5161
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005162 if (!mgmt_connected)
5163 return;
5164
Andre Guedes57eb7762013-10-30 19:01:41 -03005165 if (link_type != ACL_LINK && link_type != LE_LINK)
5166 return;
5167
Johan Hedberg744cf192011-11-08 20:40:14 +02005168 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005169
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005170 bacpy(&ev.addr.bdaddr, bdaddr);
5171 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5172 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005173
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005174 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005175
5176 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005177 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005178
Johan Hedberg124f6e32012-02-09 13:50:12 +02005179 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005180 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005181}
5182
Marcel Holtmann78929242013-10-06 23:55:47 -07005183void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5184 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005185{
Andre Guedes3655bba2013-10-30 19:01:40 -03005186 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5187 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005188 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005189 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005190
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005191 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5192 hdev);
5193
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005194 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005195 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005196 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005197
Andre Guedes3655bba2013-10-30 19:01:40 -03005198 cp = cmd->param;
5199
5200 if (bacmp(bdaddr, &cp->addr.bdaddr))
5201 return;
5202
5203 if (cp->addr.type != bdaddr_type)
5204 return;
5205
Johan Hedberg88c3df12012-02-09 14:27:38 +02005206 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005207 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005208
Marcel Holtmann78929242013-10-06 23:55:47 -07005209 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5210 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005211
Johan Hedberga664b5b2011-02-19 12:06:02 -03005212 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005213}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005214
Marcel Holtmann445608d2013-10-06 23:55:48 -07005215void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5216 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005217{
5218 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005219 struct pending_cmd *power_off;
5220
5221 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5222 if (power_off) {
5223 struct mgmt_mode *cp = power_off->param;
5224
5225 /* The connection is still in hci_conn_hash so test for 1
5226 * instead of 0 to know if this is the last one.
5227 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005228 if (!cp->val && hci_conn_count(hdev) == 1) {
5229 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005230 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005231 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005232 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005233
Johan Hedberg4c659c32011-11-07 23:13:39 +02005234 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005235 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005236 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005237
Marcel Holtmann445608d2013-10-06 23:55:48 -07005238 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005239}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005240
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005241void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005242{
5243 struct mgmt_ev_pin_code_request ev;
5244
Johan Hedbergd8457692012-02-17 14:24:57 +02005245 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005246 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005247 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005248
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005249 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005250}
5251
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005252void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5253 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005254{
5255 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005256 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005257
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005258 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005259 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005260 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005261
Johan Hedbergd8457692012-02-17 14:24:57 +02005262 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005263 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005264
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005265 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5266 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005267
Johan Hedberga664b5b2011-02-19 12:06:02 -03005268 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005269}
5270
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005271void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5272 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005273{
5274 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005275 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005276
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005277 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005278 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005279 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005280
Johan Hedbergd8457692012-02-17 14:24:57 +02005281 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005282 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005283
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005284 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5285 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005286
Johan Hedberga664b5b2011-02-19 12:06:02 -03005287 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005288}
Johan Hedberga5c29682011-02-19 12:05:57 -03005289
Johan Hedberg744cf192011-11-08 20:40:14 +02005290int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005291 u8 link_type, u8 addr_type, __le32 value,
5292 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005293{
5294 struct mgmt_ev_user_confirm_request ev;
5295
Johan Hedberg744cf192011-11-08 20:40:14 +02005296 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005297
Johan Hedberg272d90d2012-02-09 15:26:12 +02005298 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005299 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005300 ev.confirm_hint = confirm_hint;
Andrei Emeltchenko78e80982012-03-09 13:00:50 +02005301 ev.value = value;
Johan Hedberga5c29682011-02-19 12:05:57 -03005302
Johan Hedberg744cf192011-11-08 20:40:14 +02005303 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005304 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005305}
5306
Johan Hedberg272d90d2012-02-09 15:26:12 +02005307int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005308 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005309{
5310 struct mgmt_ev_user_passkey_request ev;
5311
5312 BT_DBG("%s", hdev->name);
5313
Johan Hedberg272d90d2012-02-09 15:26:12 +02005314 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005315 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005316
5317 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005318 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005319}
5320
Brian Gix0df4c182011-11-16 13:53:13 -08005321static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005322 u8 link_type, u8 addr_type, u8 status,
5323 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005324{
5325 struct pending_cmd *cmd;
5326 struct mgmt_rp_user_confirm_reply rp;
5327 int err;
5328
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005329 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005330 if (!cmd)
5331 return -ENOENT;
5332
Johan Hedberg272d90d2012-02-09 15:26:12 +02005333 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005334 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005335 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005336 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005337
Johan Hedberga664b5b2011-02-19 12:06:02 -03005338 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005339
5340 return err;
5341}
5342
Johan Hedberg744cf192011-11-08 20:40:14 +02005343int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005344 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005345{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005346 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005347 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005348}
5349
Johan Hedberg272d90d2012-02-09 15:26:12 +02005350int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005351 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005352{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005353 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005354 status,
5355 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005356}
Johan Hedberg2a611692011-02-19 12:06:00 -03005357
Brian Gix604086b2011-11-23 08:28:33 -08005358int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005359 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005360{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005361 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005362 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005363}
5364
Johan Hedberg272d90d2012-02-09 15:26:12 +02005365int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005366 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005367{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005368 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005369 status,
5370 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005371}
5372
Johan Hedberg92a25252012-09-06 18:39:26 +03005373int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5374 u8 link_type, u8 addr_type, u32 passkey,
5375 u8 entered)
5376{
5377 struct mgmt_ev_passkey_notify ev;
5378
5379 BT_DBG("%s", hdev->name);
5380
5381 bacpy(&ev.addr.bdaddr, bdaddr);
5382 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5383 ev.passkey = __cpu_to_le32(passkey);
5384 ev.entered = entered;
5385
5386 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5387}
5388
Marcel Holtmanne5460992013-10-15 14:26:23 -07005389void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5390 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005391{
5392 struct mgmt_ev_auth_failed ev;
5393
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005394 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005395 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005396 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005397
Marcel Holtmanne5460992013-10-15 14:26:23 -07005398 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005399}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005400
Marcel Holtmann464996a2013-10-15 14:26:24 -07005401void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005402{
5403 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005404 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005405
5406 if (status) {
5407 u8 mgmt_err = mgmt_status(status);
5408 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005409 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005410 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005411 }
5412
Marcel Holtmann464996a2013-10-15 14:26:24 -07005413 if (test_bit(HCI_AUTH, &hdev->flags))
5414 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5415 &hdev->dev_flags);
5416 else
5417 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5418 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005419
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005420 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005421 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005422
Johan Hedberg47990ea2012-02-22 11:58:37 +02005423 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005424 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005425
5426 if (match.sk)
5427 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005428}
5429
Johan Hedberg890ea892013-03-15 17:06:52 -05005430static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005431{
Johan Hedberg890ea892013-03-15 17:06:52 -05005432 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005433 struct hci_cp_write_eir cp;
5434
Johan Hedberg976eb202012-10-24 21:12:01 +03005435 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005436 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005437
Johan Hedbergc80da272012-02-22 15:38:48 +02005438 memset(hdev->eir, 0, sizeof(hdev->eir));
5439
Johan Hedbergcacaf522012-02-21 00:52:42 +02005440 memset(&cp, 0, sizeof(cp));
5441
Johan Hedberg890ea892013-03-15 17:06:52 -05005442 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005443}
5444
Marcel Holtmann3e248562013-10-15 14:26:25 -07005445void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005446{
5447 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005448 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005449 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005450
5451 if (status) {
5452 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005453
5454 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005455 &hdev->dev_flags)) {
5456 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005457 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005458 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005459
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005460 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5461 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005462 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005463 }
5464
5465 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005466 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005467 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005468 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5469 if (!changed)
5470 changed = test_and_clear_bit(HCI_HS_ENABLED,
5471 &hdev->dev_flags);
5472 else
5473 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005474 }
5475
5476 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5477
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005478 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005479 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005480
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005481 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005482 sock_put(match.sk);
5483
Johan Hedberg890ea892013-03-15 17:06:52 -05005484 hci_req_init(&req, hdev);
5485
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005486 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005487 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005488 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005489 clear_eir(&req);
5490
5491 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005492}
5493
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005494void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5495{
5496 struct cmd_lookup match = { NULL, hdev };
5497 bool changed = false;
5498
5499 if (status) {
5500 u8 mgmt_err = mgmt_status(status);
5501
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005502 if (enable) {
5503 if (test_and_clear_bit(HCI_SC_ENABLED,
5504 &hdev->dev_flags))
5505 new_settings(hdev, NULL);
5506 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5507 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005508
5509 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5510 cmd_status_rsp, &mgmt_err);
5511 return;
5512 }
5513
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005514 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005515 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005516 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005517 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005518 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5519 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005520
5521 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5522 settings_rsp, &match);
5523
5524 if (changed)
5525 new_settings(hdev, match.sk);
5526
5527 if (match.sk)
5528 sock_put(match.sk);
5529}
5530
Johan Hedberg92da6092013-03-15 17:06:55 -05005531static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005532{
5533 struct cmd_lookup *match = data;
5534
Johan Hedberg90e70452012-02-23 23:09:40 +02005535 if (match->sk == NULL) {
5536 match->sk = cmd->sk;
5537 sock_hold(match->sk);
5538 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005539}
5540
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005541void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5542 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005543{
Johan Hedberg90e70452012-02-23 23:09:40 +02005544 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005545
Johan Hedberg92da6092013-03-15 17:06:55 -05005546 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5547 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5548 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005549
5550 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005551 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5552 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005553
5554 if (match.sk)
5555 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005556}
5557
Marcel Holtmann7667da32013-10-15 14:26:27 -07005558void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005559{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005560 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005561 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005562
Johan Hedberg13928972013-03-15 17:07:00 -05005563 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005564 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005565
5566 memset(&ev, 0, sizeof(ev));
5567 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005568 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005569
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005570 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005571 if (!cmd) {
5572 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005573
Johan Hedberg13928972013-03-15 17:07:00 -05005574 /* If this is a HCI command related to powering on the
5575 * HCI dev don't send any mgmt signals.
5576 */
5577 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005578 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005579 }
5580
Marcel Holtmann7667da32013-10-15 14:26:27 -07005581 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5582 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005583}
Szymon Jancc35938b2011-03-22 13:12:21 +01005584
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005585void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5586 u8 *randomizer192, u8 *hash256,
5587 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005588{
5589 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005590
Johan Hedberg744cf192011-11-08 20:40:14 +02005591 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005592
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005593 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005594 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005595 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005596
5597 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005598 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5599 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005600 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005601 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5602 hash256 && randomizer256) {
5603 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005604
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005605 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5606 memcpy(rp.randomizer192, randomizer192,
5607 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005608
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005609 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5610 memcpy(rp.randomizer256, randomizer256,
5611 sizeof(rp.randomizer256));
5612
5613 cmd_complete(cmd->sk, hdev->id,
5614 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5615 &rp, sizeof(rp));
5616 } else {
5617 struct mgmt_rp_read_local_oob_data rp;
5618
5619 memcpy(rp.hash, hash192, sizeof(rp.hash));
5620 memcpy(rp.randomizer, randomizer192,
5621 sizeof(rp.randomizer));
5622
5623 cmd_complete(cmd->sk, hdev->id,
5624 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5625 &rp, sizeof(rp));
5626 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005627 }
5628
5629 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005630}
Johan Hedberge17acd42011-03-30 23:57:16 +03005631
Marcel Holtmann901801b2013-10-06 23:55:51 -07005632void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5633 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
5634 ssp, u8 *eir, u16 eir_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005635{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005636 char buf[512];
5637 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005638 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005639 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005640
Andre Guedes12602d02013-04-30 15:29:40 -03005641 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005642 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005643
Johan Hedberg1dc06092012-01-15 21:01:23 +02005644 /* Leave 5 bytes for a potential CoD field */
5645 if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005646 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005647
Johan Hedberg1dc06092012-01-15 21:01:23 +02005648 memset(buf, 0, sizeof(buf));
5649
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005650 irk = hci_get_irk(hdev, bdaddr, addr_type);
5651 if (irk) {
5652 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5653 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5654 } else {
5655 bacpy(&ev->addr.bdaddr, bdaddr);
5656 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5657 }
5658
Johan Hedberge319d2e2012-01-15 19:51:59 +02005659 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005660 if (cfm_name)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305661 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005662 if (!ssp)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305663 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005664
Johan Hedberg1dc06092012-01-15 21:01:23 +02005665 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005666 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005667
Johan Hedberg1dc06092012-01-15 21:01:23 +02005668 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5669 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005670 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005671
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005672 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005673 ev_size = sizeof(*ev) + eir_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005674
Marcel Holtmann901801b2013-10-06 23:55:51 -07005675 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005676}
Johan Hedberga88a9652011-03-30 13:18:12 +03005677
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005678void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5679 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005680{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005681 struct mgmt_ev_device_found *ev;
5682 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5683 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005684
Johan Hedbergb644ba32012-01-17 21:48:47 +02005685 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005686
Johan Hedbergb644ba32012-01-17 21:48:47 +02005687 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005688
Johan Hedbergb644ba32012-01-17 21:48:47 +02005689 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005690 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005691 ev->rssi = rssi;
5692
5693 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005694 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005695
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005696 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005697
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005698 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005699}
Johan Hedberg314b2382011-04-27 10:29:57 -04005700
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005701void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005702{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005703 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005704 struct pending_cmd *cmd;
5705
Andre Guedes343fb142011-11-22 17:14:19 -03005706 BT_DBG("%s discovering %u", hdev->name, discovering);
5707
Johan Hedberg164a6e72011-11-01 17:06:44 +02005708 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005709 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005710 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005711 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005712
5713 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005714 u8 type = hdev->discovery.type;
5715
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005716 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5717 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005718 mgmt_pending_remove(cmd);
5719 }
5720
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005721 memset(&ev, 0, sizeof(ev));
5722 ev.type = hdev->discovery.type;
5723 ev.discovering = discovering;
5724
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005725 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04005726}
Antti Julku5e762442011-08-25 16:48:02 +03005727
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005728int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005729{
5730 struct pending_cmd *cmd;
5731 struct mgmt_ev_device_blocked ev;
5732
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005733 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005734
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005735 bacpy(&ev.addr.bdaddr, bdaddr);
5736 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005737
Johan Hedberg744cf192011-11-08 20:40:14 +02005738 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005739 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005740}
5741
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005742int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005743{
5744 struct pending_cmd *cmd;
5745 struct mgmt_ev_device_unblocked ev;
5746
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005747 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005748
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005749 bacpy(&ev.addr.bdaddr, bdaddr);
5750 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005751
Johan Hedberg744cf192011-11-08 20:40:14 +02005752 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005753 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005754}
Marcel Holtmann5976e602013-10-06 04:08:14 -07005755
5756static void adv_enable_complete(struct hci_dev *hdev, u8 status)
5757{
5758 BT_DBG("%s status %u", hdev->name, status);
5759
5760 /* Clear the advertising mgmt setting if we failed to re-enable it */
5761 if (status) {
5762 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005763 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005764 }
5765}
5766
5767void mgmt_reenable_advertising(struct hci_dev *hdev)
5768{
5769 struct hci_request req;
5770
Marcel Holtmannb145edc2013-10-10 09:47:54 -07005771 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07005772 return;
5773
5774 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5775 return;
5776
5777 hci_req_init(&req, hdev);
5778 enable_advertising(&req);
5779
5780 /* If this fails we have no option but to let user space know
5781 * that we've disabled advertising.
5782 */
5783 if (hci_req_run(&req, adv_enable_complete) < 0) {
5784 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005785 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005786 }
5787}