blob: 5899ac7264ffa6a4093984295fa94674c80cc149 [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 Hedberg199a2fb2014-02-22 19:06:33 +0200820static u8 get_adv_type(struct hci_dev *hdev)
821{
822 struct pending_cmd *cmd;
823 bool connectable;
824
825 /* If there's a pending mgmt command the flag will not yet have
826 * it's final value, so check for this first.
827 */
828 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
829 if (cmd) {
830 struct mgmt_mode *cp = cmd->param;
831 connectable = !!cp->val;
832 } else {
833 connectable = test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
834 }
835
836 return connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
837}
838
839static void enable_advertising(struct hci_request *req)
840{
841 struct hci_dev *hdev = req->hdev;
842 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200843 u8 own_addr_type, enable = 0x01;
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800844 bool require_privacy;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200845
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800846 require_privacy = !test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200847
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800848 if (hci_update_random_address(req, require_privacy, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200849 return;
850
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800851 memset(&cp, 0, sizeof(cp));
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200852 cp.min_interval = __constant_cpu_to_le16(0x0800);
853 cp.max_interval = __constant_cpu_to_le16(0x0800);
854 cp.type = get_adv_type(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200855 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200856 cp.channel_map = hdev->le_adv_channel_map;
857
858 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
859
860 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
861}
862
863static void disable_advertising(struct hci_request *req)
864{
865 u8 enable = 0x00;
866
867 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
868}
869
Johan Hedberg7d785252011-12-15 00:47:39 +0200870static void service_cache_off(struct work_struct *work)
871{
872 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300873 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500874 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200875
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200876 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200877 return;
878
Johan Hedberg890ea892013-03-15 17:06:52 -0500879 hci_req_init(&req, hdev);
880
Johan Hedberg7d785252011-12-15 00:47:39 +0200881 hci_dev_lock(hdev);
882
Johan Hedberg890ea892013-03-15 17:06:52 -0500883 update_eir(&req);
884 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200885
886 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500887
888 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200889}
890
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200891static void rpa_expired(struct work_struct *work)
892{
893 struct hci_dev *hdev = container_of(work, struct hci_dev,
894 rpa_expired.work);
895 struct hci_request req;
896
897 BT_DBG("");
898
899 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
900
901 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
902 hci_conn_num(hdev, LE_LINK) > 0)
903 return;
904
905 /* The generation of a new RPA and programming it into the
906 * controller happens in the enable_advertising() function.
907 */
908
909 hci_req_init(&req, hdev);
910
911 disable_advertising(&req);
912 enable_advertising(&req);
913
914 hci_req_run(&req, NULL);
915}
916
Johan Hedberg6a919082012-02-28 06:17:26 +0200917static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200918{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200919 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200920 return;
921
Johan Hedberg4f87da82012-03-02 19:55:56 +0200922 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200923 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200924
Johan Hedberg4f87da82012-03-02 19:55:56 +0200925 /* Non-mgmt controlled devices get this bit set
926 * implicitly so that pairing works for them, however
927 * for mgmt we require user-space to explicitly enable
928 * it
929 */
930 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200931}
932
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200933static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300934 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200935{
936 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200937
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200938 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200939
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300940 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200941
Johan Hedberg03811012010-12-08 00:21:06 +0200942 memset(&rp, 0, sizeof(rp));
943
Johan Hedberg03811012010-12-08 00:21:06 +0200944 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200945
946 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200947 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200948
949 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
950 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
951
952 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200953
954 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200955 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200956
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300957 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200958
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200959 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300960 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200961}
962
963static void mgmt_pending_free(struct pending_cmd *cmd)
964{
965 sock_put(cmd->sk);
966 kfree(cmd->param);
967 kfree(cmd);
968}
969
970static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300971 struct hci_dev *hdev, void *data,
972 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200973{
974 struct pending_cmd *cmd;
975
Andre Guedes12b94562012-06-07 19:05:45 -0300976 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200977 if (!cmd)
978 return NULL;
979
980 cmd->opcode = opcode;
981 cmd->index = hdev->id;
982
Andre Guedes12b94562012-06-07 19:05:45 -0300983 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200984 if (!cmd->param) {
985 kfree(cmd);
986 return NULL;
987 }
988
989 if (data)
990 memcpy(cmd->param, data, len);
991
992 cmd->sk = sk;
993 sock_hold(sk);
994
995 list_add(&cmd->list, &hdev->mgmt_pending);
996
997 return cmd;
998}
999
1000static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001001 void (*cb)(struct pending_cmd *cmd,
1002 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001003 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001004{
Andre Guedesa3d09352013-02-01 11:21:30 -03001005 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001006
Andre Guedesa3d09352013-02-01 11:21:30 -03001007 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001008 if (opcode > 0 && cmd->opcode != opcode)
1009 continue;
1010
1011 cb(cmd, data);
1012 }
1013}
1014
Johan Hedberg03811012010-12-08 00:21:06 +02001015static void mgmt_pending_remove(struct pending_cmd *cmd)
1016{
1017 list_del(&cmd->list);
1018 mgmt_pending_free(cmd);
1019}
1020
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001021static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001022{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001023 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001024
Johan Hedbergaee9b212012-02-18 15:07:59 +02001025 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001026 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001027}
1028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001029static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001030 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001031{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001032 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001033 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001034 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001035
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001036 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001037
Johan Hedberga7e80f22013-01-09 16:05:19 +02001038 if (cp->val != 0x00 && cp->val != 0x01)
1039 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1040 MGMT_STATUS_INVALID_PARAMS);
1041
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001042 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001043
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001044 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1045 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1046 MGMT_STATUS_BUSY);
1047 goto failed;
1048 }
1049
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001050 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1051 cancel_delayed_work(&hdev->power_off);
1052
1053 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001054 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1055 data, len);
1056 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001057 goto failed;
1058 }
1059 }
1060
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001061 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001062 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001063 goto failed;
1064 }
1065
Johan Hedberg03811012010-12-08 00:21:06 +02001066 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1067 if (!cmd) {
1068 err = -ENOMEM;
1069 goto failed;
1070 }
1071
1072 if (cp->val)
Johan Hedberg19202572013-01-14 22:33:51 +02001073 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg03811012010-12-08 00:21:06 +02001074 else
Johan Hedberg19202572013-01-14 22:33:51 +02001075 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg03811012010-12-08 00:21:06 +02001076
1077 err = 0;
1078
1079failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001080 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001081 return err;
1082}
1083
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001084static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1085 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001086{
1087 struct sk_buff *skb;
1088 struct mgmt_hdr *hdr;
1089
Andre Guedes790eff42012-06-07 19:05:46 -03001090 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001091 if (!skb)
1092 return -ENOMEM;
1093
1094 hdr = (void *) skb_put(skb, sizeof(*hdr));
1095 hdr->opcode = cpu_to_le16(event);
1096 if (hdev)
1097 hdr->index = cpu_to_le16(hdev->id);
1098 else
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05301099 hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001100 hdr->len = cpu_to_le16(data_len);
1101
1102 if (data)
1103 memcpy(skb_put(skb, data_len), data, data_len);
1104
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001105 /* Time stamp */
1106 __net_timestamp(skb);
1107
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001108 hci_send_to_control(skb, skip_sk);
1109 kfree_skb(skb);
1110
1111 return 0;
1112}
1113
1114static int new_settings(struct hci_dev *hdev, struct sock *skip)
1115{
1116 __le32 ev;
1117
1118 ev = cpu_to_le32(get_current_settings(hdev));
1119
1120 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1121}
1122
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001123struct cmd_lookup {
1124 struct sock *sk;
1125 struct hci_dev *hdev;
1126 u8 mgmt_status;
1127};
1128
1129static void settings_rsp(struct pending_cmd *cmd, void *data)
1130{
1131 struct cmd_lookup *match = data;
1132
1133 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1134
1135 list_del(&cmd->list);
1136
1137 if (match->sk == NULL) {
1138 match->sk = cmd->sk;
1139 sock_hold(match->sk);
1140 }
1141
1142 mgmt_pending_free(cmd);
1143}
1144
1145static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1146{
1147 u8 *status = data;
1148
1149 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1150 mgmt_pending_remove(cmd);
1151}
1152
Johan Hedberge6fe7982013-10-02 15:45:22 +03001153static u8 mgmt_bredr_support(struct hci_dev *hdev)
1154{
1155 if (!lmp_bredr_capable(hdev))
1156 return MGMT_STATUS_NOT_SUPPORTED;
1157 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1158 return MGMT_STATUS_REJECTED;
1159 else
1160 return MGMT_STATUS_SUCCESS;
1161}
1162
1163static u8 mgmt_le_support(struct hci_dev *hdev)
1164{
1165 if (!lmp_le_capable(hdev))
1166 return MGMT_STATUS_NOT_SUPPORTED;
1167 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1168 return MGMT_STATUS_REJECTED;
1169 else
1170 return MGMT_STATUS_SUCCESS;
1171}
1172
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001173static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1174{
1175 struct pending_cmd *cmd;
1176 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001177 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001178 bool changed;
1179
1180 BT_DBG("status 0x%02x", status);
1181
1182 hci_dev_lock(hdev);
1183
1184 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1185 if (!cmd)
1186 goto unlock;
1187
1188 if (status) {
1189 u8 mgmt_err = mgmt_status(status);
1190 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001191 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001192 goto remove_cmd;
1193 }
1194
1195 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001196 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001197 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1198 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001199
1200 if (hdev->discov_timeout > 0) {
1201 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1202 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1203 to);
1204 }
1205 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001206 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1207 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001208 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001209
1210 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1211
1212 if (changed)
1213 new_settings(hdev, cmd->sk);
1214
Marcel Holtmann970ba522013-10-15 06:33:57 -07001215 /* When the discoverable mode gets changed, make sure
1216 * that class of device has the limited discoverable
1217 * bit correctly set.
1218 */
1219 hci_req_init(&req, hdev);
1220 update_class(&req);
1221 hci_req_run(&req, NULL);
1222
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001223remove_cmd:
1224 mgmt_pending_remove(cmd);
1225
1226unlock:
1227 hci_dev_unlock(hdev);
1228}
1229
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001230static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001231 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001232{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001233 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001234 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001235 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001236 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001237 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001238 int err;
1239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001240 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001241
Johan Hedberg9a43e252013-10-20 19:00:07 +03001242 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1243 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001244 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001245 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001246
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001247 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001248 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1249 MGMT_STATUS_INVALID_PARAMS);
1250
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001251 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001252
1253 /* Disabling discoverable requires that no timeout is set,
1254 * and enabling limited discoverable requires a timeout.
1255 */
1256 if ((cp->val == 0x00 && timeout > 0) ||
1257 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001258 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001259 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001260
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001261 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001262
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001263 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001264 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001265 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001266 goto failed;
1267 }
1268
1269 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001270 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001271 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001272 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001273 goto failed;
1274 }
1275
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001276 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001277 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001278 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001279 goto failed;
1280 }
1281
1282 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001283 bool changed = false;
1284
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001285 /* Setting limited discoverable when powered off is
1286 * not a valid operation since it requires a timeout
1287 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1288 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001289 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1290 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1291 changed = true;
1292 }
1293
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001294 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001295 if (err < 0)
1296 goto failed;
1297
1298 if (changed)
1299 err = new_settings(hdev, sk);
1300
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001301 goto failed;
1302 }
1303
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001304 /* If the current mode is the same, then just update the timeout
1305 * value with the new value. And if only the timeout gets updated,
1306 * then no need for any HCI transactions.
1307 */
1308 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1309 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1310 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001311 cancel_delayed_work(&hdev->discov_off);
1312 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001313
Marcel Holtmann36261542013-10-15 08:28:51 -07001314 if (cp->val && hdev->discov_timeout > 0) {
1315 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001316 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001317 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001318 }
1319
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001320 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001321 goto failed;
1322 }
1323
1324 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1325 if (!cmd) {
1326 err = -ENOMEM;
1327 goto failed;
1328 }
1329
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001330 /* Cancel any potential discoverable timeout that might be
1331 * still active and store new timeout value. The arming of
1332 * the timeout happens in the complete handler.
1333 */
1334 cancel_delayed_work(&hdev->discov_off);
1335 hdev->discov_timeout = timeout;
1336
Johan Hedbergb456f872013-10-19 23:38:22 +03001337 /* Limited discoverable mode */
1338 if (cp->val == 0x02)
1339 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1340 else
1341 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1342
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001343 hci_req_init(&req, hdev);
1344
Johan Hedberg9a43e252013-10-20 19:00:07 +03001345 /* The procedure for LE-only controllers is much simpler - just
1346 * update the advertising data.
1347 */
1348 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1349 goto update_ad;
1350
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001351 scan = SCAN_PAGE;
1352
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001353 if (cp->val) {
1354 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001355
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001356 if (cp->val == 0x02) {
1357 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001358 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001359 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1360 hci_cp.iac_lap[1] = 0x8b;
1361 hci_cp.iac_lap[2] = 0x9e;
1362 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1363 hci_cp.iac_lap[4] = 0x8b;
1364 hci_cp.iac_lap[5] = 0x9e;
1365 } else {
1366 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001367 hci_cp.num_iac = 1;
1368 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1369 hci_cp.iac_lap[1] = 0x8b;
1370 hci_cp.iac_lap[2] = 0x9e;
1371 }
1372
1373 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1374 (hci_cp.num_iac * 3) + 1, &hci_cp);
1375
1376 scan |= SCAN_INQUIRY;
1377 } else {
1378 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1379 }
1380
1381 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001382
Johan Hedberg9a43e252013-10-20 19:00:07 +03001383update_ad:
1384 update_adv_data(&req);
1385
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001386 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001387 if (err < 0)
1388 mgmt_pending_remove(cmd);
1389
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001390failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001391 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001392 return err;
1393}
1394
Johan Hedberg406d7802013-03-15 17:07:09 -05001395static void write_fast_connectable(struct hci_request *req, bool enable)
1396{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001397 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001398 struct hci_cp_write_page_scan_activity acp;
1399 u8 type;
1400
Johan Hedberg547003b2013-10-21 16:51:53 +03001401 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1402 return;
1403
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001404 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1405 return;
1406
Johan Hedberg406d7802013-03-15 17:07:09 -05001407 if (enable) {
1408 type = PAGE_SCAN_TYPE_INTERLACED;
1409
1410 /* 160 msec page scan interval */
1411 acp.interval = __constant_cpu_to_le16(0x0100);
1412 } else {
1413 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1414
1415 /* default 1.28 sec page scan */
1416 acp.interval = __constant_cpu_to_le16(0x0800);
1417 }
1418
1419 acp.window = __constant_cpu_to_le16(0x0012);
1420
Johan Hedbergbd98b992013-03-15 17:07:13 -05001421 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1422 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1423 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1424 sizeof(acp), &acp);
1425
1426 if (hdev->page_scan_type != type)
1427 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001428}
1429
Johan Hedberg2b76f452013-03-15 17:07:04 -05001430static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1431{
1432 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001433 struct mgmt_mode *cp;
1434 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001435
1436 BT_DBG("status 0x%02x", status);
1437
1438 hci_dev_lock(hdev);
1439
1440 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1441 if (!cmd)
1442 goto unlock;
1443
Johan Hedberg37438c12013-10-14 16:20:05 +03001444 if (status) {
1445 u8 mgmt_err = mgmt_status(status);
1446 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1447 goto remove_cmd;
1448 }
1449
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001450 cp = cmd->param;
1451 if (cp->val)
1452 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1453 else
1454 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1455
Johan Hedberg2b76f452013-03-15 17:07:04 -05001456 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1457
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001458 if (changed)
1459 new_settings(hdev, cmd->sk);
1460
Johan Hedberg37438c12013-10-14 16:20:05 +03001461remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001462 mgmt_pending_remove(cmd);
1463
1464unlock:
1465 hci_dev_unlock(hdev);
1466}
1467
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001468static int set_connectable_update_settings(struct hci_dev *hdev,
1469 struct sock *sk, u8 val)
1470{
1471 bool changed = false;
1472 int err;
1473
1474 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1475 changed = true;
1476
1477 if (val) {
1478 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1479 } else {
1480 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1481 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1482 }
1483
1484 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1485 if (err < 0)
1486 return err;
1487
1488 if (changed)
1489 return new_settings(hdev, sk);
1490
1491 return 0;
1492}
1493
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001494static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001495 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001496{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001497 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001498 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001499 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001500 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001501 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001502
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001503 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001504
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001505 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1506 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001507 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001508 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001509
Johan Hedberga7e80f22013-01-09 16:05:19 +02001510 if (cp->val != 0x00 && cp->val != 0x01)
1511 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1512 MGMT_STATUS_INVALID_PARAMS);
1513
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001514 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001515
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001516 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001517 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001518 goto failed;
1519 }
1520
1521 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001522 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001523 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001524 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001525 goto failed;
1526 }
1527
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001528 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1529 if (!cmd) {
1530 err = -ENOMEM;
1531 goto failed;
1532 }
1533
Johan Hedberg2b76f452013-03-15 17:07:04 -05001534 hci_req_init(&req, hdev);
1535
Johan Hedberg9a43e252013-10-20 19:00:07 +03001536 /* If BR/EDR is not enabled and we disable advertising as a
1537 * by-product of disabling connectable, we need to update the
1538 * advertising flags.
1539 */
1540 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1541 if (!cp->val) {
1542 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1543 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1544 }
1545 update_adv_data(&req);
1546 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001547 if (cp->val) {
1548 scan = SCAN_PAGE;
1549 } else {
1550 scan = 0;
1551
1552 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001553 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001554 cancel_delayed_work(&hdev->discov_off);
1555 }
1556
1557 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1558 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001559
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001560 /* If we're going from non-connectable to connectable or
1561 * vice-versa when fast connectable is enabled ensure that fast
1562 * connectable gets disabled. write_fast_connectable won't do
1563 * anything if the page scan parameters are already what they
1564 * should be.
1565 */
1566 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001567 write_fast_connectable(&req, false);
1568
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001569 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1570 hci_conn_num(hdev, LE_LINK) == 0) {
1571 disable_advertising(&req);
1572 enable_advertising(&req);
1573 }
1574
Johan Hedberg2b76f452013-03-15 17:07:04 -05001575 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001576 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001577 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001578 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001579 err = set_connectable_update_settings(hdev, sk,
1580 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001581 goto failed;
1582 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001583
1584failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001585 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001586 return err;
1587}
1588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001589static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001590 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001591{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001592 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001593 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001594 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001595
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001596 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001597
Johan Hedberga7e80f22013-01-09 16:05:19 +02001598 if (cp->val != 0x00 && cp->val != 0x01)
1599 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1600 MGMT_STATUS_INVALID_PARAMS);
1601
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001602 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001603
1604 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001605 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001606 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001607 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001608
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001609 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001610 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001611 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001612
Marcel Holtmann55594352013-10-06 16:11:57 -07001613 if (changed)
1614 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001615
Marcel Holtmann55594352013-10-06 16:11:57 -07001616unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001617 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001618 return err;
1619}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001620
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001621static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1622 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001623{
1624 struct mgmt_mode *cp = data;
1625 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001626 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001627 int err;
1628
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001629 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001630
Johan Hedberge6fe7982013-10-02 15:45:22 +03001631 status = mgmt_bredr_support(hdev);
1632 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001633 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001634 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001635
Johan Hedberga7e80f22013-01-09 16:05:19 +02001636 if (cp->val != 0x00 && cp->val != 0x01)
1637 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1638 MGMT_STATUS_INVALID_PARAMS);
1639
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001640 hci_dev_lock(hdev);
1641
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001642 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001643 bool changed = false;
1644
1645 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001646 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001647 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1648 changed = true;
1649 }
1650
1651 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1652 if (err < 0)
1653 goto failed;
1654
1655 if (changed)
1656 err = new_settings(hdev, sk);
1657
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001658 goto failed;
1659 }
1660
1661 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001662 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001663 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001664 goto failed;
1665 }
1666
1667 val = !!cp->val;
1668
1669 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1670 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1671 goto failed;
1672 }
1673
1674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
1680 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1681 if (err < 0) {
1682 mgmt_pending_remove(cmd);
1683 goto failed;
1684 }
1685
1686failed:
1687 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001688 return err;
1689}
1690
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001691static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001692{
1693 struct mgmt_mode *cp = data;
1694 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001695 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001696 int err;
1697
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001698 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001699
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001700 status = mgmt_bredr_support(hdev);
1701 if (status)
1702 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1703
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001704 if (!lmp_ssp_capable(hdev))
1705 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1706 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001707
Johan Hedberga7e80f22013-01-09 16:05:19 +02001708 if (cp->val != 0x00 && cp->val != 0x01)
1709 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1710 MGMT_STATUS_INVALID_PARAMS);
1711
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001712 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001713
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001714 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001715 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001716
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001717 if (cp->val) {
1718 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1719 &hdev->dev_flags);
1720 } else {
1721 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1722 &hdev->dev_flags);
1723 if (!changed)
1724 changed = test_and_clear_bit(HCI_HS_ENABLED,
1725 &hdev->dev_flags);
1726 else
1727 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001728 }
1729
1730 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1731 if (err < 0)
1732 goto failed;
1733
1734 if (changed)
1735 err = new_settings(hdev, sk);
1736
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001737 goto failed;
1738 }
1739
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001740 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1741 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001742 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1743 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001744 goto failed;
1745 }
1746
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001747 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001748 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1749 goto failed;
1750 }
1751
1752 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1753 if (!cmd) {
1754 err = -ENOMEM;
1755 goto failed;
1756 }
1757
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001758 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001759 if (err < 0) {
1760 mgmt_pending_remove(cmd);
1761 goto failed;
1762 }
1763
1764failed:
1765 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001766 return err;
1767}
1768
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001769static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001770{
1771 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001772 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001773 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001774 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001775
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001776 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001777
Johan Hedberge6fe7982013-10-02 15:45:22 +03001778 status = mgmt_bredr_support(hdev);
1779 if (status)
1780 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001781
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001782 if (!lmp_ssp_capable(hdev))
1783 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1784 MGMT_STATUS_NOT_SUPPORTED);
1785
1786 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1787 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1788 MGMT_STATUS_REJECTED);
1789
Johan Hedberga7e80f22013-01-09 16:05:19 +02001790 if (cp->val != 0x00 && cp->val != 0x01)
1791 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1792 MGMT_STATUS_INVALID_PARAMS);
1793
Marcel Holtmannee392692013-10-01 22:59:23 -07001794 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001795
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001796 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001797 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001798 } else {
1799 if (hdev_is_powered(hdev)) {
1800 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1801 MGMT_STATUS_REJECTED);
1802 goto unlock;
1803 }
1804
Marcel Holtmannee392692013-10-01 22:59:23 -07001805 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001806 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001807
1808 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1809 if (err < 0)
1810 goto unlock;
1811
1812 if (changed)
1813 err = new_settings(hdev, sk);
1814
1815unlock:
1816 hci_dev_unlock(hdev);
1817 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001818}
1819
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001820static void le_enable_complete(struct hci_dev *hdev, u8 status)
1821{
1822 struct cmd_lookup match = { NULL, hdev };
1823
1824 if (status) {
1825 u8 mgmt_err = mgmt_status(status);
1826
1827 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1828 &mgmt_err);
1829 return;
1830 }
1831
1832 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1833
1834 new_settings(hdev, match.sk);
1835
1836 if (match.sk)
1837 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001838
1839 /* Make sure the controller has a good default for
1840 * advertising data. Restrict the update to when LE
1841 * has actually been enabled. During power on, the
1842 * update in powered_update_hci will take care of it.
1843 */
1844 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1845 struct hci_request req;
1846
1847 hci_dev_lock(hdev);
1848
1849 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001850 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001851 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001852 hci_req_run(&req, NULL);
1853
1854 hci_dev_unlock(hdev);
1855 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001856}
1857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001859{
1860 struct mgmt_mode *cp = data;
1861 struct hci_cp_write_le_host_supported hci_cp;
1862 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001863 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001864 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001865 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001867 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001868
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001869 if (!lmp_le_capable(hdev))
1870 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1871 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001872
Johan Hedberga7e80f22013-01-09 16:05:19 +02001873 if (cp->val != 0x00 && cp->val != 0x01)
1874 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1875 MGMT_STATUS_INVALID_PARAMS);
1876
Johan Hedbergc73eee92013-04-19 18:35:21 +03001877 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03001878 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03001879 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1880 MGMT_STATUS_REJECTED);
1881
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001882 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001883
1884 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001885 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001886
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001887 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02001888 bool changed = false;
1889
1890 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1891 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1892 changed = true;
1893 }
1894
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02001895 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
1896 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03001897 changed = true;
1898 }
1899
Johan Hedberg06199cf2012-02-22 16:37:11 +02001900 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1901 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08001902 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001903
1904 if (changed)
1905 err = new_settings(hdev, sk);
1906
Johan Hedberg1de028c2012-02-29 19:55:35 -08001907 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001908 }
1909
Johan Hedberg4375f102013-09-25 13:26:10 +03001910 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
1911 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001912 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001913 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001914 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001915 }
1916
1917 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
1918 if (!cmd) {
1919 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08001920 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001921 }
1922
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001923 hci_req_init(&req, hdev);
1924
Johan Hedberg06199cf2012-02-22 16:37:11 +02001925 memset(&hci_cp, 0, sizeof(hci_cp));
1926
1927 if (val) {
1928 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001929 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001930 } else {
1931 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1932 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001933 }
1934
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001935 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
1936 &hci_cp);
1937
1938 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05301939 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001940 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001941
Johan Hedberg1de028c2012-02-29 19:55:35 -08001942unlock:
1943 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001944 return err;
1945}
1946
Johan Hedberg0cab9c82013-03-15 17:06:54 -05001947/* This is a helper function to test for pending mgmt commands that can
1948 * cause CoD or EIR HCI commands. We can only allow one such pending
1949 * mgmt command at a time since otherwise we cannot easily track what
1950 * the current values are, will be, and based on that calculate if a new
1951 * HCI command needs to be sent and if yes with what value.
1952 */
1953static bool pending_eir_or_class(struct hci_dev *hdev)
1954{
1955 struct pending_cmd *cmd;
1956
1957 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
1958 switch (cmd->opcode) {
1959 case MGMT_OP_ADD_UUID:
1960 case MGMT_OP_REMOVE_UUID:
1961 case MGMT_OP_SET_DEV_CLASS:
1962 case MGMT_OP_SET_POWERED:
1963 return true;
1964 }
1965 }
1966
1967 return false;
1968}
1969
Johan Hedberg83be8ec2013-01-27 00:31:29 +02001970static const u8 bluetooth_base_uuid[] = {
1971 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
1972 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1973};
1974
1975static u8 get_uuid_size(const u8 *uuid)
1976{
1977 u32 val;
1978
1979 if (memcmp(uuid, bluetooth_base_uuid, 12))
1980 return 128;
1981
1982 val = get_unaligned_le32(&uuid[12]);
1983 if (val > 0xffff)
1984 return 32;
1985
1986 return 16;
1987}
1988
Johan Hedberg92da6092013-03-15 17:06:55 -05001989static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
1990{
1991 struct pending_cmd *cmd;
1992
1993 hci_dev_lock(hdev);
1994
1995 cmd = mgmt_pending_find(mgmt_op, hdev);
1996 if (!cmd)
1997 goto unlock;
1998
1999 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2000 hdev->dev_class, 3);
2001
2002 mgmt_pending_remove(cmd);
2003
2004unlock:
2005 hci_dev_unlock(hdev);
2006}
2007
2008static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2009{
2010 BT_DBG("status 0x%02x", status);
2011
2012 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2013}
2014
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002015static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002016{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002017 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002018 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002019 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002020 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002021 int err;
2022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002023 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002024
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002025 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002026
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002027 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002028 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002029 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002030 goto failed;
2031 }
2032
Andre Guedes92c4c202012-06-07 19:05:44 -03002033 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002034 if (!uuid) {
2035 err = -ENOMEM;
2036 goto failed;
2037 }
2038
2039 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002040 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002041 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002042
Johan Hedbergde66aa62013-01-27 00:31:27 +02002043 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002044
Johan Hedberg890ea892013-03-15 17:06:52 -05002045 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002046
Johan Hedberg890ea892013-03-15 17:06:52 -05002047 update_class(&req);
2048 update_eir(&req);
2049
Johan Hedberg92da6092013-03-15 17:06:55 -05002050 err = hci_req_run(&req, add_uuid_complete);
2051 if (err < 0) {
2052 if (err != -ENODATA)
2053 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002054
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002055 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002056 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002057 goto failed;
2058 }
2059
2060 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002061 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002062 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002063 goto failed;
2064 }
2065
2066 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002067
2068failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002069 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002070 return err;
2071}
2072
Johan Hedberg24b78d02012-02-23 23:24:30 +02002073static bool enable_service_cache(struct hci_dev *hdev)
2074{
2075 if (!hdev_is_powered(hdev))
2076 return false;
2077
2078 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002079 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2080 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002081 return true;
2082 }
2083
2084 return false;
2085}
2086
Johan Hedberg92da6092013-03-15 17:06:55 -05002087static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2088{
2089 BT_DBG("status 0x%02x", status);
2090
2091 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2092}
2093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002094static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002095 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002096{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002097 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002098 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002099 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002100 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 -05002101 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002102 int err, found;
2103
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002104 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002105
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002106 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002107
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002108 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002109 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002110 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002111 goto unlock;
2112 }
2113
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002114 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002115 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002116
Johan Hedberg24b78d02012-02-23 23:24:30 +02002117 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002118 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002119 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002120 goto unlock;
2121 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002122
Johan Hedberg9246a862012-02-23 21:33:16 +02002123 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002124 }
2125
2126 found = 0;
2127
Johan Hedberg056341c2013-01-27 00:31:30 +02002128 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002129 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2130 continue;
2131
2132 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002133 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002134 found++;
2135 }
2136
2137 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002138 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002139 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002140 goto unlock;
2141 }
2142
Johan Hedberg9246a862012-02-23 21:33:16 +02002143update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002144 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002145
Johan Hedberg890ea892013-03-15 17:06:52 -05002146 update_class(&req);
2147 update_eir(&req);
2148
Johan Hedberg92da6092013-03-15 17:06:55 -05002149 err = hci_req_run(&req, remove_uuid_complete);
2150 if (err < 0) {
2151 if (err != -ENODATA)
2152 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002155 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002156 goto unlock;
2157 }
2158
2159 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002160 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002161 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002162 goto unlock;
2163 }
2164
2165 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002166
2167unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002168 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002169 return err;
2170}
2171
Johan Hedberg92da6092013-03-15 17:06:55 -05002172static void set_class_complete(struct hci_dev *hdev, u8 status)
2173{
2174 BT_DBG("status 0x%02x", status);
2175
2176 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2177}
2178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002179static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002180 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002181{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002182 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002183 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002184 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002185 int err;
2186
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002187 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002188
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002189 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002190 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2191 MGMT_STATUS_NOT_SUPPORTED);
2192
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002193 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002194
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002195 if (pending_eir_or_class(hdev)) {
2196 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2197 MGMT_STATUS_BUSY);
2198 goto unlock;
2199 }
2200
2201 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2202 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2203 MGMT_STATUS_INVALID_PARAMS);
2204 goto unlock;
2205 }
2206
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002207 hdev->major_class = cp->major;
2208 hdev->minor_class = cp->minor;
2209
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002210 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002211 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002212 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002213 goto unlock;
2214 }
2215
Johan Hedberg890ea892013-03-15 17:06:52 -05002216 hci_req_init(&req, hdev);
2217
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002218 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002219 hci_dev_unlock(hdev);
2220 cancel_delayed_work_sync(&hdev->service_cache);
2221 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002222 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002223 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002224
Johan Hedberg890ea892013-03-15 17:06:52 -05002225 update_class(&req);
2226
Johan Hedberg92da6092013-03-15 17:06:55 -05002227 err = hci_req_run(&req, set_class_complete);
2228 if (err < 0) {
2229 if (err != -ENODATA)
2230 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002231
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002232 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002233 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002234 goto unlock;
2235 }
2236
2237 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002238 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002239 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002240 goto unlock;
2241 }
2242
2243 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002244
Johan Hedbergb5235a62012-02-21 14:32:24 +02002245unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002246 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002247 return err;
2248}
2249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002250static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002251 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002252{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002253 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002254 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002255 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002256 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002257
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002258 BT_DBG("request for %s", hdev->name);
2259
2260 if (!lmp_bredr_capable(hdev))
2261 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2262 MGMT_STATUS_NOT_SUPPORTED);
2263
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002264 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002265
Johan Hedberg86742e12011-11-07 23:13:38 +02002266 expected_len = sizeof(*cp) + key_count *
2267 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002268 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002269 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002270 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002271 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002272 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002273 }
2274
Johan Hedberg4ae14302013-01-20 14:27:13 +02002275 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2276 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2277 MGMT_STATUS_INVALID_PARAMS);
2278
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002279 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002280 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002281
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002282 for (i = 0; i < key_count; i++) {
2283 struct mgmt_link_key_info *key = &cp->keys[i];
2284
Marcel Holtmann8e991132014-01-10 02:07:25 -08002285 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002286 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2287 MGMT_STATUS_INVALID_PARAMS);
2288 }
2289
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002290 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002291
2292 hci_link_keys_clear(hdev);
2293
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002294 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002295 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002296 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002297 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2298
2299 if (changed)
2300 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002301
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002302 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002303 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002304
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002305 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002306 key->type, key->pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002307 }
2308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002309 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002310
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002311 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002312
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002313 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002314}
2315
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002316static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002317 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002318{
2319 struct mgmt_ev_device_unpaired ev;
2320
2321 bacpy(&ev.addr.bdaddr, bdaddr);
2322 ev.addr.type = addr_type;
2323
2324 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002325 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002326}
2327
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002328static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002329 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002330{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002331 struct mgmt_cp_unpair_device *cp = data;
2332 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002333 struct hci_cp_disconnect dc;
2334 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002335 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002336 int err;
2337
Johan Hedberga8a1d192011-11-10 15:54:38 +02002338 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002339 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2340 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002341
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002342 if (!bdaddr_type_is_valid(cp->addr.type))
2343 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2344 MGMT_STATUS_INVALID_PARAMS,
2345 &rp, sizeof(rp));
2346
Johan Hedberg118da702013-01-20 14:27:20 +02002347 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2348 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2349 MGMT_STATUS_INVALID_PARAMS,
2350 &rp, sizeof(rp));
2351
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002352 hci_dev_lock(hdev);
2353
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002354 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002355 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002356 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002357 goto unlock;
2358 }
2359
Johan Hedberge0b2b272014-02-18 17:14:31 +02002360 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002361 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002362 } else {
2363 u8 addr_type;
2364
2365 if (cp->addr.type == BDADDR_LE_PUBLIC)
2366 addr_type = ADDR_LE_DEV_PUBLIC;
2367 else
2368 addr_type = ADDR_LE_DEV_RANDOM;
2369
Johan Hedberga7ec7332014-02-18 17:14:35 +02002370 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2371
Johan Hedberge0b2b272014-02-18 17:14:31 +02002372 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2373 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002374
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002375 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002376 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002377 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002378 goto unlock;
2379 }
2380
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002381 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002382 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002383 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002384 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002385 else
2386 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002387 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002388 } else {
2389 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002390 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002391
Johan Hedberga8a1d192011-11-10 15:54:38 +02002392 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002393 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002394 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002395 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002396 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002397 }
2398
Johan Hedberg124f6e32012-02-09 13:50:12 +02002399 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002400 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002401 if (!cmd) {
2402 err = -ENOMEM;
2403 goto unlock;
2404 }
2405
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002406 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002407 dc.reason = 0x13; /* Remote User Terminated Connection */
2408 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2409 if (err < 0)
2410 mgmt_pending_remove(cmd);
2411
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002412unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002413 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002414 return err;
2415}
2416
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002417static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002418 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002419{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002420 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002421 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002422 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002423 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002424 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002425 int err;
2426
2427 BT_DBG("");
2428
Johan Hedberg06a63b12013-01-20 14:27:21 +02002429 memset(&rp, 0, sizeof(rp));
2430 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2431 rp.addr.type = cp->addr.type;
2432
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002433 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002434 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2435 MGMT_STATUS_INVALID_PARAMS,
2436 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002437
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002438 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002439
2440 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002441 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2442 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002443 goto failed;
2444 }
2445
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002446 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002447 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2448 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002449 goto failed;
2450 }
2451
Andre Guedes591f47f2012-04-24 21:02:49 -03002452 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002453 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2454 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002455 else
2456 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002457
Vishal Agarwalf9607272012-06-13 05:32:43 +05302458 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002459 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2460 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002461 goto failed;
2462 }
2463
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002464 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002465 if (!cmd) {
2466 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002467 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002468 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002469
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002470 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002471 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002472
2473 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2474 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002475 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002476
2477failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002478 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002479 return err;
2480}
2481
Andre Guedes57c14772012-04-24 21:02:50 -03002482static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002483{
2484 switch (link_type) {
2485 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002486 switch (addr_type) {
2487 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002488 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002489
Johan Hedberg48264f02011-11-09 13:58:58 +02002490 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002491 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002492 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002493 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002494
Johan Hedberg4c659c32011-11-07 23:13:39 +02002495 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002496 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002497 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002498 }
2499}
2500
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002501static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2502 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002503{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002504 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002505 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002506 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002507 int err;
2508 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002509
2510 BT_DBG("");
2511
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002512 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002513
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002514 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002515 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002516 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002517 goto unlock;
2518 }
2519
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002520 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002521 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2522 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002523 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002524 }
2525
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002526 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002527 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002528 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002529 err = -ENOMEM;
2530 goto unlock;
2531 }
2532
Johan Hedberg2784eb42011-01-21 13:56:35 +02002533 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002534 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002535 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2536 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002537 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002538 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002539 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002540 continue;
2541 i++;
2542 }
2543
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002544 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002545
Johan Hedberg4c659c32011-11-07 23:13:39 +02002546 /* Recalculate length in case of filtered SCO connections, etc */
2547 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002548
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002549 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002550 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002551
Johan Hedberga38528f2011-01-22 06:46:43 +02002552 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002553
2554unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002555 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002556 return err;
2557}
2558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002559static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002560 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002561{
2562 struct pending_cmd *cmd;
2563 int err;
2564
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002565 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002566 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002567 if (!cmd)
2568 return -ENOMEM;
2569
Johan Hedbergd8457692012-02-17 14:24:57 +02002570 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002571 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002572 if (err < 0)
2573 mgmt_pending_remove(cmd);
2574
2575 return err;
2576}
2577
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002578static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002579 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002580{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002581 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002582 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002583 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002584 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002585 int err;
2586
2587 BT_DBG("");
2588
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002589 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002590
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002591 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002593 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002594 goto failed;
2595 }
2596
Johan Hedbergd8457692012-02-17 14:24:57 +02002597 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002598 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002599 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002600 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002601 goto failed;
2602 }
2603
2604 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002605 struct mgmt_cp_pin_code_neg_reply ncp;
2606
2607 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002608
2609 BT_ERR("PIN code is not 16 bytes long");
2610
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002611 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002612 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002613 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002614 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002615
2616 goto failed;
2617 }
2618
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002619 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002620 if (!cmd) {
2621 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002622 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002623 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002624
Johan Hedbergd8457692012-02-17 14:24:57 +02002625 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002626 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002627 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002628
2629 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2630 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002631 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002632
2633failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002634 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002635 return err;
2636}
2637
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002638static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2639 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002640{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002641 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002642
2643 BT_DBG("");
2644
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002645 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002646
2647 hdev->io_capability = cp->io_capability;
2648
2649 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002650 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002651
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002652 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002653
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002654 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2655 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002656}
2657
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002658static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002659{
2660 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002661 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002662
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002663 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002664 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2665 continue;
2666
Johan Hedberge9a416b2011-02-19 12:05:56 -03002667 if (cmd->user_data != conn)
2668 continue;
2669
2670 return cmd;
2671 }
2672
2673 return NULL;
2674}
2675
2676static void pairing_complete(struct pending_cmd *cmd, u8 status)
2677{
2678 struct mgmt_rp_pair_device rp;
2679 struct hci_conn *conn = cmd->user_data;
2680
Johan Hedbergba4e5642011-11-11 00:07:34 +02002681 bacpy(&rp.addr.bdaddr, &conn->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002682 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002683
Johan Hedbergaee9b212012-02-18 15:07:59 +02002684 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002685 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002686
2687 /* So we don't get further callbacks for this connection */
2688 conn->connect_cfm_cb = NULL;
2689 conn->security_cfm_cb = NULL;
2690 conn->disconn_cfm_cb = NULL;
2691
David Herrmann76a68ba2013-04-06 20:28:37 +02002692 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002693
Johan Hedberga664b5b2011-02-19 12:06:02 -03002694 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002695}
2696
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002697void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2698{
2699 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2700 struct pending_cmd *cmd;
2701
2702 cmd = find_pairing(conn);
2703 if (cmd)
2704 pairing_complete(cmd, status);
2705}
2706
Johan Hedberge9a416b2011-02-19 12:05:56 -03002707static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2708{
2709 struct pending_cmd *cmd;
2710
2711 BT_DBG("status %u", status);
2712
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002713 cmd = find_pairing(conn);
2714 if (!cmd)
2715 BT_DBG("Unable to find a pending command");
2716 else
Johan Hedberge2113262012-02-18 15:20:03 +02002717 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002718}
2719
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002720static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302721{
2722 struct pending_cmd *cmd;
2723
2724 BT_DBG("status %u", status);
2725
2726 if (!status)
2727 return;
2728
2729 cmd = find_pairing(conn);
2730 if (!cmd)
2731 BT_DBG("Unable to find a pending command");
2732 else
2733 pairing_complete(cmd, mgmt_status(status));
2734}
2735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002736static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002737 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002738{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002739 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002740 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002741 struct pending_cmd *cmd;
2742 u8 sec_level, auth_type;
2743 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002744 int err;
2745
2746 BT_DBG("");
2747
Szymon Jancf950a30e2013-01-18 12:48:07 +01002748 memset(&rp, 0, sizeof(rp));
2749 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2750 rp.addr.type = cp->addr.type;
2751
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002752 if (!bdaddr_type_is_valid(cp->addr.type))
2753 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2754 MGMT_STATUS_INVALID_PARAMS,
2755 &rp, sizeof(rp));
2756
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002757 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002758
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002759 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002760 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2761 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002762 goto unlock;
2763 }
2764
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002765 sec_level = BT_SECURITY_MEDIUM;
2766 if (cp->io_cap == 0x03)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002767 auth_type = HCI_AT_DEDICATED_BONDING;
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002768 else
Johan Hedberge9a416b2011-02-19 12:05:56 -03002769 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002770
Andre Guedes591f47f2012-04-24 21:02:49 -03002771 if (cp->addr.type == BDADDR_BREDR)
Andre Guedesb12f62c2012-04-24 21:02:54 -03002772 conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr,
2773 cp->addr.type, sec_level, auth_type);
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002774 else
Andre Guedesb12f62c2012-04-24 21:02:54 -03002775 conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr,
2776 cp->addr.type, sec_level, auth_type);
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002777
Ville Tervo30e76272011-02-22 16:10:53 -03002778 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002779 int status;
2780
2781 if (PTR_ERR(conn) == -EBUSY)
2782 status = MGMT_STATUS_BUSY;
2783 else
2784 status = MGMT_STATUS_CONNECT_FAILED;
2785
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002786 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002787 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002788 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002789 goto unlock;
2790 }
2791
2792 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002793 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002794 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002795 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002796 goto unlock;
2797 }
2798
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002799 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002800 if (!cmd) {
2801 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002802 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002803 goto unlock;
2804 }
2805
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002806 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002807 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002808 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002809 conn->security_cfm_cb = pairing_complete_cb;
2810 conn->disconn_cfm_cb = pairing_complete_cb;
2811 } else {
2812 conn->connect_cfm_cb = le_pairing_complete_cb;
2813 conn->security_cfm_cb = le_pairing_complete_cb;
2814 conn->disconn_cfm_cb = le_pairing_complete_cb;
2815 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002816
Johan Hedberge9a416b2011-02-19 12:05:56 -03002817 conn->io_capability = cp->io_cap;
2818 cmd->user_data = conn;
2819
2820 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002821 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002822 pairing_complete(cmd, 0);
2823
2824 err = 0;
2825
2826unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002827 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002828 return err;
2829}
2830
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002831static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2832 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002833{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002834 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002835 struct pending_cmd *cmd;
2836 struct hci_conn *conn;
2837 int err;
2838
2839 BT_DBG("");
2840
Johan Hedberg28424702012-02-02 04:02:29 +02002841 hci_dev_lock(hdev);
2842
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002843 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002844 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002845 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002846 goto unlock;
2847 }
2848
Johan Hedberg28424702012-02-02 04:02:29 +02002849 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2850 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002851 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002852 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002853 goto unlock;
2854 }
2855
2856 conn = cmd->user_data;
2857
2858 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002859 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002860 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002861 goto unlock;
2862 }
2863
2864 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2865
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002866 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002867 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02002868unlock:
2869 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02002870 return err;
2871}
2872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002873static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05002874 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002875 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03002876{
Johan Hedberga5c29682011-02-19 12:05:57 -03002877 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08002878 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002879 int err;
2880
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002881 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02002882
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002883 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002884 err = cmd_complete(sk, hdev->id, mgmt_op,
2885 MGMT_STATUS_NOT_POWERED, addr,
2886 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08002887 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002888 }
2889
Johan Hedberg1707c602013-03-15 17:07:15 -05002890 if (addr->type == BDADDR_BREDR)
2891 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02002892 else
Johan Hedberg1707c602013-03-15 17:07:15 -05002893 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08002894
Johan Hedberg272d90d2012-02-09 15:26:12 +02002895 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002896 err = cmd_complete(sk, hdev->id, mgmt_op,
2897 MGMT_STATUS_NOT_CONNECTED, addr,
2898 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02002899 goto done;
2900 }
2901
Johan Hedberg1707c602013-03-15 17:07:15 -05002902 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08002903 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08002904 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08002905
Brian Gix5fe57d92011-12-21 16:12:13 -08002906 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002907 err = cmd_complete(sk, hdev->id, mgmt_op,
2908 MGMT_STATUS_SUCCESS, addr,
2909 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08002910 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002911 err = cmd_complete(sk, hdev->id, mgmt_op,
2912 MGMT_STATUS_FAILED, addr,
2913 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08002914
Brian Gix47c15e22011-11-16 13:53:14 -08002915 goto done;
2916 }
2917
Johan Hedberg1707c602013-03-15 17:07:15 -05002918 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03002919 if (!cmd) {
2920 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08002921 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002922 }
2923
Brian Gix0df4c182011-11-16 13:53:13 -08002924 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08002925 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
2926 struct hci_cp_user_passkey_reply cp;
2927
Johan Hedberg1707c602013-03-15 17:07:15 -05002928 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08002929 cp.passkey = passkey;
2930 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
2931 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05002932 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
2933 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08002934
Johan Hedberga664b5b2011-02-19 12:06:02 -03002935 if (err < 0)
2936 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03002937
Brian Gix0df4c182011-11-16 13:53:13 -08002938done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002939 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03002940 return err;
2941}
2942
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05302943static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
2944 void *data, u16 len)
2945{
2946 struct mgmt_cp_pin_code_neg_reply *cp = data;
2947
2948 BT_DBG("");
2949
Johan Hedberg1707c602013-03-15 17:07:15 -05002950 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05302951 MGMT_OP_PIN_CODE_NEG_REPLY,
2952 HCI_OP_PIN_CODE_NEG_REPLY, 0);
2953}
2954
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002955static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
2956 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08002957{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002958 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08002959
2960 BT_DBG("");
2961
2962 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002963 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002964 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08002965
Johan Hedberg1707c602013-03-15 17:07:15 -05002966 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002967 MGMT_OP_USER_CONFIRM_REPLY,
2968 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08002969}
2970
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002971static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002972 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08002973{
Johan Hedbergc9c26592011-12-15 00:47:41 +02002974 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08002975
2976 BT_DBG("");
2977
Johan Hedberg1707c602013-03-15 17:07:15 -05002978 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979 MGMT_OP_USER_CONFIRM_NEG_REPLY,
2980 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08002981}
2982
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002983static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
2984 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08002985{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002986 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08002987
2988 BT_DBG("");
2989
Johan Hedberg1707c602013-03-15 17:07:15 -05002990 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002991 MGMT_OP_USER_PASSKEY_REPLY,
2992 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08002993}
2994
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002995static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002996 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08002997{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002998 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08002999
3000 BT_DBG("");
3001
Johan Hedberg1707c602013-03-15 17:07:15 -05003002 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003003 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3004 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003005}
3006
Johan Hedberg13928972013-03-15 17:07:00 -05003007static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003008{
Johan Hedberg13928972013-03-15 17:07:00 -05003009 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003010 struct hci_cp_write_local_name cp;
3011
Johan Hedberg13928972013-03-15 17:07:00 -05003012 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003013
Johan Hedberg890ea892013-03-15 17:06:52 -05003014 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003015}
3016
Johan Hedberg13928972013-03-15 17:07:00 -05003017static void set_name_complete(struct hci_dev *hdev, u8 status)
3018{
3019 struct mgmt_cp_set_local_name *cp;
3020 struct pending_cmd *cmd;
3021
3022 BT_DBG("status 0x%02x", status);
3023
3024 hci_dev_lock(hdev);
3025
3026 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3027 if (!cmd)
3028 goto unlock;
3029
3030 cp = cmd->param;
3031
3032 if (status)
3033 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3034 mgmt_status(status));
3035 else
3036 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3037 cp, sizeof(*cp));
3038
3039 mgmt_pending_remove(cmd);
3040
3041unlock:
3042 hci_dev_unlock(hdev);
3043}
3044
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003045static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003046 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003047{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003048 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003049 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003050 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003051 int err;
3052
3053 BT_DBG("");
3054
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003055 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003056
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003057 /* If the old values are the same as the new ones just return a
3058 * direct command complete event.
3059 */
3060 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3061 !memcmp(hdev->short_name, cp->short_name,
3062 sizeof(hdev->short_name))) {
3063 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3064 data, len);
3065 goto failed;
3066 }
3067
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003068 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003069
Johan Hedbergb5235a62012-02-21 14:32:24 +02003070 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003071 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003072
3073 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003074 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003075 if (err < 0)
3076 goto failed;
3077
3078 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003079 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003080
Johan Hedbergb5235a62012-02-21 14:32:24 +02003081 goto failed;
3082 }
3083
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003084 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003085 if (!cmd) {
3086 err = -ENOMEM;
3087 goto failed;
3088 }
3089
Johan Hedberg13928972013-03-15 17:07:00 -05003090 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3091
Johan Hedberg890ea892013-03-15 17:06:52 -05003092 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003093
3094 if (lmp_bredr_capable(hdev)) {
3095 update_name(&req);
3096 update_eir(&req);
3097 }
3098
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003099 /* The name is stored in the scan response data and so
3100 * no need to udpate the advertising data here.
3101 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003102 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003103 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003104
Johan Hedberg13928972013-03-15 17:07:00 -05003105 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003106 if (err < 0)
3107 mgmt_pending_remove(cmd);
3108
3109failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003110 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003111 return err;
3112}
3113
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003114static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003115 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003116{
Szymon Jancc35938b2011-03-22 13:12:21 +01003117 struct pending_cmd *cmd;
3118 int err;
3119
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003120 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003121
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003122 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003123
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003124 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003125 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003126 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003127 goto unlock;
3128 }
3129
Andre Guedes9a1a1992012-07-24 15:03:48 -03003130 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003131 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003132 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003133 goto unlock;
3134 }
3135
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003136 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003137 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003138 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003139 goto unlock;
3140 }
3141
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003142 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003143 if (!cmd) {
3144 err = -ENOMEM;
3145 goto unlock;
3146 }
3147
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003148 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3149 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3150 0, NULL);
3151 else
3152 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3153
Szymon Jancc35938b2011-03-22 13:12:21 +01003154 if (err < 0)
3155 mgmt_pending_remove(cmd);
3156
3157unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003158 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003159 return err;
3160}
3161
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003162static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003163 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003164{
Szymon Janc2763eda2011-03-22 13:12:22 +01003165 int err;
3166
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003167 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003168
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003169 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003170
Marcel Holtmannec109112014-01-10 02:07:30 -08003171 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3172 struct mgmt_cp_add_remote_oob_data *cp = data;
3173 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003174
Marcel Holtmannec109112014-01-10 02:07:30 -08003175 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3176 cp->hash, cp->randomizer);
3177 if (err < 0)
3178 status = MGMT_STATUS_FAILED;
3179 else
3180 status = MGMT_STATUS_SUCCESS;
3181
3182 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3183 status, &cp->addr, sizeof(cp->addr));
3184 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3185 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3186 u8 status;
3187
3188 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3189 cp->hash192,
3190 cp->randomizer192,
3191 cp->hash256,
3192 cp->randomizer256);
3193 if (err < 0)
3194 status = MGMT_STATUS_FAILED;
3195 else
3196 status = MGMT_STATUS_SUCCESS;
3197
3198 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3199 status, &cp->addr, sizeof(cp->addr));
3200 } else {
3201 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3202 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3203 MGMT_STATUS_INVALID_PARAMS);
3204 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003205
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003206 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003207 return err;
3208}
3209
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003210static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003211 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003212{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003213 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003214 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003215 int err;
3216
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003217 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003218
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003219 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003220
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003221 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003222 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003223 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003224 else
Szymon Janca6785be2012-12-13 15:11:21 +01003225 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003226
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003227 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003228 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003229
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003230 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003231 return err;
3232}
3233
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003234static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3235{
3236 struct pending_cmd *cmd;
3237 u8 type;
3238 int err;
3239
3240 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3241
3242 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3243 if (!cmd)
3244 return -ENOENT;
3245
3246 type = hdev->discovery.type;
3247
3248 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3249 &type, sizeof(type));
3250 mgmt_pending_remove(cmd);
3251
3252 return err;
3253}
3254
Andre Guedes7c307722013-04-30 15:29:28 -03003255static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3256{
3257 BT_DBG("status %d", status);
3258
3259 if (status) {
3260 hci_dev_lock(hdev);
3261 mgmt_start_discovery_failed(hdev, status);
3262 hci_dev_unlock(hdev);
3263 return;
3264 }
3265
3266 hci_dev_lock(hdev);
3267 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3268 hci_dev_unlock(hdev);
3269
3270 switch (hdev->discovery.type) {
3271 case DISCOV_TYPE_LE:
3272 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003273 DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003274 break;
3275
3276 case DISCOV_TYPE_INTERLEAVED:
3277 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003278 DISCOV_INTERLEAVED_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003279 break;
3280
3281 case DISCOV_TYPE_BREDR:
3282 break;
3283
3284 default:
3285 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3286 }
3287}
3288
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003289static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003290 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003291{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003292 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003293 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003294 struct hci_cp_le_set_scan_param param_cp;
3295 struct hci_cp_le_set_scan_enable enable_cp;
3296 struct hci_cp_inquiry inq_cp;
3297 struct hci_request req;
3298 /* General inquiry access code (GIAC) */
3299 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003300 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003301 int err;
3302
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003303 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003304
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003305 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003306
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003307 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003308 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003309 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003310 goto failed;
3311 }
3312
Andre Guedes642be6c2012-03-21 00:03:37 -03003313 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3314 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3315 MGMT_STATUS_BUSY);
3316 goto failed;
3317 }
3318
Johan Hedbergff9ef572012-01-04 14:23:45 +02003319 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003320 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003321 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003322 goto failed;
3323 }
3324
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003325 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003326 if (!cmd) {
3327 err = -ENOMEM;
3328 goto failed;
3329 }
3330
Andre Guedes4aab14e2012-02-17 20:39:36 -03003331 hdev->discovery.type = cp->type;
3332
Andre Guedes7c307722013-04-30 15:29:28 -03003333 hci_req_init(&req, hdev);
3334
Andre Guedes4aab14e2012-02-17 20:39:36 -03003335 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003336 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003337 status = mgmt_bredr_support(hdev);
3338 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003339 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003340 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003341 mgmt_pending_remove(cmd);
3342 goto failed;
3343 }
3344
Andre Guedes7c307722013-04-30 15:29:28 -03003345 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3346 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3347 MGMT_STATUS_BUSY);
3348 mgmt_pending_remove(cmd);
3349 goto failed;
3350 }
3351
3352 hci_inquiry_cache_flush(hdev);
3353
3354 memset(&inq_cp, 0, sizeof(inq_cp));
3355 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003356 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003357 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003358 break;
3359
3360 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003361 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003362 status = mgmt_le_support(hdev);
3363 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003364 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003365 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003366 mgmt_pending_remove(cmd);
3367 goto failed;
3368 }
3369
Andre Guedes7c307722013-04-30 15:29:28 -03003370 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003371 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003372 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3373 MGMT_STATUS_NOT_SUPPORTED);
3374 mgmt_pending_remove(cmd);
3375 goto failed;
3376 }
3377
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003378 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003379 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3380 MGMT_STATUS_REJECTED);
3381 mgmt_pending_remove(cmd);
3382 goto failed;
3383 }
3384
3385 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
3386 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3387 MGMT_STATUS_BUSY);
3388 mgmt_pending_remove(cmd);
3389 goto failed;
3390 }
3391
3392 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003393
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003394 /* All active scans will be done with either a resolvable
3395 * private address (when privacy feature has been enabled)
3396 * or unresolvable private address.
3397 */
3398 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003399 if (err < 0) {
3400 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3401 MGMT_STATUS_FAILED);
3402 mgmt_pending_remove(cmd);
3403 goto failed;
3404 }
3405
Andre Guedes7c307722013-04-30 15:29:28 -03003406 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003407 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3408 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003409 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003410 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3411 &param_cp);
3412
3413 memset(&enable_cp, 0, sizeof(enable_cp));
3414 enable_cp.enable = LE_SCAN_ENABLE;
3415 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3416 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3417 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003418 break;
3419
Andre Guedesf39799f2012-02-17 20:39:35 -03003420 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003421 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3422 MGMT_STATUS_INVALID_PARAMS);
3423 mgmt_pending_remove(cmd);
3424 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003425 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003426
Andre Guedes7c307722013-04-30 15:29:28 -03003427 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003428 if (err < 0)
3429 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003430 else
3431 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003432
3433failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003434 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003435 return err;
3436}
3437
Andre Guedes1183fdc2013-04-30 15:29:35 -03003438static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3439{
3440 struct pending_cmd *cmd;
3441 int err;
3442
3443 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3444 if (!cmd)
3445 return -ENOENT;
3446
3447 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3448 &hdev->discovery.type, sizeof(hdev->discovery.type));
3449 mgmt_pending_remove(cmd);
3450
3451 return err;
3452}
3453
Andre Guedes0e05bba2013-04-30 15:29:33 -03003454static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3455{
3456 BT_DBG("status %d", status);
3457
3458 hci_dev_lock(hdev);
3459
3460 if (status) {
3461 mgmt_stop_discovery_failed(hdev, status);
3462 goto unlock;
3463 }
3464
3465 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3466
3467unlock:
3468 hci_dev_unlock(hdev);
3469}
3470
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003471static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003472 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003473{
Johan Hedbergd9306502012-02-20 23:25:18 +02003474 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003475 struct pending_cmd *cmd;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003476 struct hci_cp_remote_name_req_cancel cp;
3477 struct inquiry_entry *e;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003478 struct hci_request req;
3479 struct hci_cp_le_set_scan_enable enable_cp;
Johan Hedberg14a53662011-04-27 10:29:56 -04003480 int err;
3481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003483
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003484 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003485
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003486 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003487 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003488 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3489 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003490 goto unlock;
3491 }
3492
3493 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003494 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003495 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3496 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003497 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003498 }
3499
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003500 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003501 if (!cmd) {
3502 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003503 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003504 }
3505
Andre Guedes0e05bba2013-04-30 15:29:33 -03003506 hci_req_init(&req, hdev);
3507
Andre Guedese0d9727e2012-03-20 15:15:36 -03003508 switch (hdev->discovery.state) {
3509 case DISCOVERY_FINDING:
Andre Guedes0e05bba2013-04-30 15:29:33 -03003510 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3511 hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
3512 } else {
3513 cancel_delayed_work(&hdev->le_scan_disable);
3514
3515 memset(&enable_cp, 0, sizeof(enable_cp));
3516 enable_cp.enable = LE_SCAN_DISABLE;
3517 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
3518 sizeof(enable_cp), &enable_cp);
3519 }
Andre Guedesc9ecc482012-03-15 16:52:08 -03003520
Andre Guedese0d9727e2012-03-20 15:15:36 -03003521 break;
3522
3523 case DISCOVERY_RESOLVING:
3524 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003525 NAME_PENDING);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003526 if (!e) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003527 mgmt_pending_remove(cmd);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003528 err = cmd_complete(sk, hdev->id,
3529 MGMT_OP_STOP_DISCOVERY, 0,
3530 &mgmt_cp->type,
3531 sizeof(mgmt_cp->type));
3532 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3533 goto unlock;
3534 }
3535
3536 bacpy(&cp.bdaddr, &e->data.bdaddr);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003537 hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
3538 &cp);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003539
3540 break;
3541
3542 default:
3543 BT_DBG("unknown discovery state %u", hdev->discovery.state);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003544
3545 mgmt_pending_remove(cmd);
3546 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
3547 MGMT_STATUS_FAILED, &mgmt_cp->type,
3548 sizeof(mgmt_cp->type));
3549 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003550 }
3551
Andre Guedes0e05bba2013-04-30 15:29:33 -03003552 err = hci_req_run(&req, stop_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003553 if (err < 0)
3554 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003555 else
3556 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003557
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003558unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003559 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003560 return err;
3561}
3562
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003563static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003564 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003565{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003566 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003567 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003568 int err;
3569
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003570 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003571
Johan Hedberg561aafb2012-01-04 13:31:59 +02003572 hci_dev_lock(hdev);
3573
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003574 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003575 err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003576 MGMT_STATUS_FAILED);
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003577 goto failed;
3578 }
3579
Johan Hedberga198e7b2012-02-17 14:27:06 +02003580 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003581 if (!e) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003582 err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003583 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003584 goto failed;
3585 }
3586
3587 if (cp->name_known) {
3588 e->name_state = NAME_KNOWN;
3589 list_del(&e->list);
3590 } else {
3591 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003592 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003593 }
3594
Johan Hedberge3846622013-01-09 15:29:33 +02003595 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3596 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003597
3598failed:
3599 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003600 return err;
3601}
3602
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003603static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003604 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003605{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003606 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003607 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003608 int err;
3609
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003610 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003611
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003612 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003613 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3614 MGMT_STATUS_INVALID_PARAMS,
3615 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003616
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003617 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003618
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003619 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003620 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003621 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003622 else
Szymon Janca6785be2012-12-13 15:11:21 +01003623 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003624
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003625 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003626 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003627
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003628 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003629
3630 return err;
3631}
3632
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003633static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003634 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003635{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003636 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003637 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003638 int err;
3639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003640 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003641
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003642 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003643 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3644 MGMT_STATUS_INVALID_PARAMS,
3645 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003646
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003647 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003648
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003649 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003650 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003651 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003652 else
Szymon Janca6785be2012-12-13 15:11:21 +01003653 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003654
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003655 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003656 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003657
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003658 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003659
3660 return err;
3661}
3662
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003663static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3664 u16 len)
3665{
3666 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003667 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003668 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003669 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003670
3671 BT_DBG("%s", hdev->name);
3672
Szymon Jancc72d4b82012-03-16 16:02:57 +01003673 source = __le16_to_cpu(cp->source);
3674
3675 if (source > 0x0002)
3676 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3677 MGMT_STATUS_INVALID_PARAMS);
3678
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003679 hci_dev_lock(hdev);
3680
Szymon Jancc72d4b82012-03-16 16:02:57 +01003681 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003682 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3683 hdev->devid_product = __le16_to_cpu(cp->product);
3684 hdev->devid_version = __le16_to_cpu(cp->version);
3685
3686 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3687
Johan Hedberg890ea892013-03-15 17:06:52 -05003688 hci_req_init(&req, hdev);
3689 update_eir(&req);
3690 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003691
3692 hci_dev_unlock(hdev);
3693
3694 return err;
3695}
3696
Johan Hedberg4375f102013-09-25 13:26:10 +03003697static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3698{
3699 struct cmd_lookup match = { NULL, hdev };
3700
3701 if (status) {
3702 u8 mgmt_err = mgmt_status(status);
3703
3704 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3705 cmd_status_rsp, &mgmt_err);
3706 return;
3707 }
3708
3709 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3710 &match);
3711
3712 new_settings(hdev, match.sk);
3713
3714 if (match.sk)
3715 sock_put(match.sk);
3716}
3717
Marcel Holtmann21b51872013-10-10 09:47:53 -07003718static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3719 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003720{
3721 struct mgmt_mode *cp = data;
3722 struct pending_cmd *cmd;
3723 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003724 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003725 int err;
3726
3727 BT_DBG("request for %s", hdev->name);
3728
Johan Hedberge6fe7982013-10-02 15:45:22 +03003729 status = mgmt_le_support(hdev);
3730 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003731 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003732 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003733
3734 if (cp->val != 0x00 && cp->val != 0x01)
3735 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3736 MGMT_STATUS_INVALID_PARAMS);
3737
3738 hci_dev_lock(hdev);
3739
3740 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003741 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003742
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003743 /* The following conditions are ones which mean that we should
3744 * not do any HCI communication but directly send a mgmt
3745 * response to user space (after toggling the flag if
3746 * necessary).
3747 */
3748 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003749 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003750 bool changed = false;
3751
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003752 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3753 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003754 changed = true;
3755 }
3756
3757 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3758 if (err < 0)
3759 goto unlock;
3760
3761 if (changed)
3762 err = new_settings(hdev, sk);
3763
3764 goto unlock;
3765 }
3766
3767 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3768 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3769 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3770 MGMT_STATUS_BUSY);
3771 goto unlock;
3772 }
3773
3774 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3775 if (!cmd) {
3776 err = -ENOMEM;
3777 goto unlock;
3778 }
3779
3780 hci_req_init(&req, hdev);
3781
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003782 if (val)
3783 enable_advertising(&req);
3784 else
3785 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003786
3787 err = hci_req_run(&req, set_advertising_complete);
3788 if (err < 0)
3789 mgmt_pending_remove(cmd);
3790
3791unlock:
3792 hci_dev_unlock(hdev);
3793 return err;
3794}
3795
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003796static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3797 void *data, u16 len)
3798{
3799 struct mgmt_cp_set_static_address *cp = data;
3800 int err;
3801
3802 BT_DBG("%s", hdev->name);
3803
Marcel Holtmann62af4442013-10-02 22:10:32 -07003804 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003805 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003806 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003807
3808 if (hdev_is_powered(hdev))
3809 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3810 MGMT_STATUS_REJECTED);
3811
3812 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3813 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3814 return cmd_status(sk, hdev->id,
3815 MGMT_OP_SET_STATIC_ADDRESS,
3816 MGMT_STATUS_INVALID_PARAMS);
3817
3818 /* Two most significant bits shall be set */
3819 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3820 return cmd_status(sk, hdev->id,
3821 MGMT_OP_SET_STATIC_ADDRESS,
3822 MGMT_STATUS_INVALID_PARAMS);
3823 }
3824
3825 hci_dev_lock(hdev);
3826
3827 bacpy(&hdev->static_addr, &cp->bdaddr);
3828
3829 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3830
3831 hci_dev_unlock(hdev);
3832
3833 return err;
3834}
3835
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003836static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3837 void *data, u16 len)
3838{
3839 struct mgmt_cp_set_scan_params *cp = data;
3840 __u16 interval, window;
3841 int err;
3842
3843 BT_DBG("%s", hdev->name);
3844
3845 if (!lmp_le_capable(hdev))
3846 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3847 MGMT_STATUS_NOT_SUPPORTED);
3848
3849 interval = __le16_to_cpu(cp->interval);
3850
3851 if (interval < 0x0004 || interval > 0x4000)
3852 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3853 MGMT_STATUS_INVALID_PARAMS);
3854
3855 window = __le16_to_cpu(cp->window);
3856
3857 if (window < 0x0004 || window > 0x4000)
3858 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3859 MGMT_STATUS_INVALID_PARAMS);
3860
Marcel Holtmann899e1072013-10-14 09:55:32 -07003861 if (window > interval)
3862 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3863 MGMT_STATUS_INVALID_PARAMS);
3864
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003865 hci_dev_lock(hdev);
3866
3867 hdev->le_scan_interval = interval;
3868 hdev->le_scan_window = window;
3869
3870 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3871
3872 hci_dev_unlock(hdev);
3873
3874 return err;
3875}
3876
Johan Hedberg33e38b32013-03-15 17:07:05 -05003877static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3878{
3879 struct pending_cmd *cmd;
3880
3881 BT_DBG("status 0x%02x", status);
3882
3883 hci_dev_lock(hdev);
3884
3885 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3886 if (!cmd)
3887 goto unlock;
3888
3889 if (status) {
3890 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3891 mgmt_status(status));
3892 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05003893 struct mgmt_mode *cp = cmd->param;
3894
3895 if (cp->val)
3896 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
3897 else
3898 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
3899
Johan Hedberg33e38b32013-03-15 17:07:05 -05003900 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3901 new_settings(hdev, cmd->sk);
3902 }
3903
3904 mgmt_pending_remove(cmd);
3905
3906unlock:
3907 hci_dev_unlock(hdev);
3908}
3909
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003910static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003911 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03003912{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003913 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05003914 struct pending_cmd *cmd;
3915 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03003916 int err;
3917
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003918 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003919
Johan Hedberg56f87902013-10-02 13:43:13 +03003920 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
3921 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03003922 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3923 MGMT_STATUS_NOT_SUPPORTED);
3924
Johan Hedberga7e80f22013-01-09 16:05:19 +02003925 if (cp->val != 0x00 && cp->val != 0x01)
3926 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3927 MGMT_STATUS_INVALID_PARAMS);
3928
Johan Hedberg5400c042012-02-21 16:40:33 +02003929 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003930 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003931 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02003932
3933 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003934 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003935 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003936
3937 hci_dev_lock(hdev);
3938
Johan Hedberg05cbf292013-03-15 17:07:07 -05003939 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
3940 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
3941 MGMT_STATUS_BUSY);
3942 goto unlock;
3943 }
3944
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05003945 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
3946 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
3947 hdev);
3948 goto unlock;
3949 }
3950
Johan Hedberg33e38b32013-03-15 17:07:05 -05003951 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
3952 data, len);
3953 if (!cmd) {
3954 err = -ENOMEM;
3955 goto unlock;
3956 }
3957
3958 hci_req_init(&req, hdev);
3959
Johan Hedberg406d7802013-03-15 17:07:09 -05003960 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05003961
3962 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003963 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003964 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003965 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05003966 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03003967 }
3968
Johan Hedberg33e38b32013-03-15 17:07:05 -05003969unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03003970 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05003971
Antti Julkuf6422ec2011-06-22 13:11:56 +03003972 return err;
3973}
3974
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03003975static void set_bredr_scan(struct hci_request *req)
3976{
3977 struct hci_dev *hdev = req->hdev;
3978 u8 scan = 0;
3979
3980 /* Ensure that fast connectable is disabled. This function will
3981 * not do anything if the page scan parameters are already what
3982 * they should be.
3983 */
3984 write_fast_connectable(req, false);
3985
3986 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
3987 scan |= SCAN_PAGE;
3988 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
3989 scan |= SCAN_INQUIRY;
3990
3991 if (scan)
3992 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
3993}
3994
Johan Hedberg0663ca22013-10-02 13:43:14 +03003995static void set_bredr_complete(struct hci_dev *hdev, u8 status)
3996{
3997 struct pending_cmd *cmd;
3998
3999 BT_DBG("status 0x%02x", status);
4000
4001 hci_dev_lock(hdev);
4002
4003 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4004 if (!cmd)
4005 goto unlock;
4006
4007 if (status) {
4008 u8 mgmt_err = mgmt_status(status);
4009
4010 /* We need to restore the flag if related HCI commands
4011 * failed.
4012 */
4013 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4014
4015 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4016 } else {
4017 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4018 new_settings(hdev, cmd->sk);
4019 }
4020
4021 mgmt_pending_remove(cmd);
4022
4023unlock:
4024 hci_dev_unlock(hdev);
4025}
4026
4027static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4028{
4029 struct mgmt_mode *cp = data;
4030 struct pending_cmd *cmd;
4031 struct hci_request req;
4032 int err;
4033
4034 BT_DBG("request for %s", hdev->name);
4035
4036 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4037 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4038 MGMT_STATUS_NOT_SUPPORTED);
4039
4040 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4041 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4042 MGMT_STATUS_REJECTED);
4043
4044 if (cp->val != 0x00 && cp->val != 0x01)
4045 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4046 MGMT_STATUS_INVALID_PARAMS);
4047
4048 hci_dev_lock(hdev);
4049
4050 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4051 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4052 goto unlock;
4053 }
4054
4055 if (!hdev_is_powered(hdev)) {
4056 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004057 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4058 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4059 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4060 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4061 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4062 }
4063
4064 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4065
4066 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4067 if (err < 0)
4068 goto unlock;
4069
4070 err = new_settings(hdev, sk);
4071 goto unlock;
4072 }
4073
4074 /* Reject disabling when powered on */
4075 if (!cp->val) {
4076 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4077 MGMT_STATUS_REJECTED);
4078 goto unlock;
4079 }
4080
4081 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4082 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4083 MGMT_STATUS_BUSY);
4084 goto unlock;
4085 }
4086
4087 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4088 if (!cmd) {
4089 err = -ENOMEM;
4090 goto unlock;
4091 }
4092
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004093 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004094 * generates the correct flags.
4095 */
4096 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4097
4098 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004099
4100 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4101 set_bredr_scan(&req);
4102
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004103 /* Since only the advertising data flags will change, there
4104 * is no need to update the scan response data.
4105 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004106 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004107
Johan Hedberg0663ca22013-10-02 13:43:14 +03004108 err = hci_req_run(&req, set_bredr_complete);
4109 if (err < 0)
4110 mgmt_pending_remove(cmd);
4111
4112unlock:
4113 hci_dev_unlock(hdev);
4114 return err;
4115}
4116
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004117static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4118 void *data, u16 len)
4119{
4120 struct mgmt_mode *cp = data;
4121 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004122 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004123 int err;
4124
4125 BT_DBG("request for %s", hdev->name);
4126
4127 status = mgmt_bredr_support(hdev);
4128 if (status)
4129 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4130 status);
4131
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004132 if (!lmp_sc_capable(hdev) &&
4133 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004134 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4135 MGMT_STATUS_NOT_SUPPORTED);
4136
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004137 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004138 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4139 MGMT_STATUS_INVALID_PARAMS);
4140
4141 hci_dev_lock(hdev);
4142
4143 if (!hdev_is_powered(hdev)) {
4144 bool changed;
4145
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004146 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004147 changed = !test_and_set_bit(HCI_SC_ENABLED,
4148 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004149 if (cp->val == 0x02)
4150 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4151 else
4152 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4153 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004154 changed = test_and_clear_bit(HCI_SC_ENABLED,
4155 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004156 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4157 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004158
4159 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4160 if (err < 0)
4161 goto failed;
4162
4163 if (changed)
4164 err = new_settings(hdev, sk);
4165
4166 goto failed;
4167 }
4168
4169 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4170 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4171 MGMT_STATUS_BUSY);
4172 goto failed;
4173 }
4174
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004175 val = !!cp->val;
4176
4177 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4178 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004179 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4180 goto failed;
4181 }
4182
4183 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4184 if (!cmd) {
4185 err = -ENOMEM;
4186 goto failed;
4187 }
4188
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004189 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004190 if (err < 0) {
4191 mgmt_pending_remove(cmd);
4192 goto failed;
4193 }
4194
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004195 if (cp->val == 0x02)
4196 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4197 else
4198 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4199
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004200failed:
4201 hci_dev_unlock(hdev);
4202 return err;
4203}
4204
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004205static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4206 void *data, u16 len)
4207{
4208 struct mgmt_mode *cp = data;
4209 bool changed;
4210 int err;
4211
4212 BT_DBG("request for %s", hdev->name);
4213
4214 if (cp->val != 0x00 && cp->val != 0x01)
4215 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4216 MGMT_STATUS_INVALID_PARAMS);
4217
4218 hci_dev_lock(hdev);
4219
4220 if (cp->val)
4221 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4222 else
4223 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4224
4225 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4226 if (err < 0)
4227 goto unlock;
4228
4229 if (changed)
4230 err = new_settings(hdev, sk);
4231
4232unlock:
4233 hci_dev_unlock(hdev);
4234 return err;
4235}
4236
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004237static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4238 u16 len)
4239{
4240 struct mgmt_cp_set_privacy *cp = cp_data;
4241 bool changed;
4242 int err;
4243
4244 BT_DBG("request for %s", hdev->name);
4245
4246 if (!lmp_le_capable(hdev))
4247 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4248 MGMT_STATUS_NOT_SUPPORTED);
4249
4250 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4251 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4252 MGMT_STATUS_INVALID_PARAMS);
4253
4254 if (hdev_is_powered(hdev))
4255 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4256 MGMT_STATUS_REJECTED);
4257
4258 hci_dev_lock(hdev);
4259
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004260 /* If user space supports this command it is also expected to
4261 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4262 */
4263 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4264
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004265 if (cp->privacy) {
4266 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4267 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4268 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4269 } else {
4270 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4271 memset(hdev->irk, 0, sizeof(hdev->irk));
4272 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4273 }
4274
4275 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4276 if (err < 0)
4277 goto unlock;
4278
4279 if (changed)
4280 err = new_settings(hdev, sk);
4281
4282unlock:
4283 hci_dev_unlock(hdev);
4284 return err;
4285}
4286
Johan Hedberg41edf162014-02-18 10:19:35 +02004287static bool irk_is_valid(struct mgmt_irk_info *irk)
4288{
4289 switch (irk->addr.type) {
4290 case BDADDR_LE_PUBLIC:
4291 return true;
4292
4293 case BDADDR_LE_RANDOM:
4294 /* Two most significant bits shall be set */
4295 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4296 return false;
4297 return true;
4298 }
4299
4300 return false;
4301}
4302
4303static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4304 u16 len)
4305{
4306 struct mgmt_cp_load_irks *cp = cp_data;
4307 u16 irk_count, expected_len;
4308 int i, err;
4309
4310 BT_DBG("request for %s", hdev->name);
4311
4312 if (!lmp_le_capable(hdev))
4313 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4314 MGMT_STATUS_NOT_SUPPORTED);
4315
4316 irk_count = __le16_to_cpu(cp->irk_count);
4317
4318 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4319 if (expected_len != len) {
4320 BT_ERR("load_irks: expected %u bytes, got %u bytes",
4321 len, expected_len);
4322 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4323 MGMT_STATUS_INVALID_PARAMS);
4324 }
4325
4326 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4327
4328 for (i = 0; i < irk_count; i++) {
4329 struct mgmt_irk_info *key = &cp->irks[i];
4330
4331 if (!irk_is_valid(key))
4332 return cmd_status(sk, hdev->id,
4333 MGMT_OP_LOAD_IRKS,
4334 MGMT_STATUS_INVALID_PARAMS);
4335 }
4336
4337 hci_dev_lock(hdev);
4338
4339 hci_smp_irks_clear(hdev);
4340
4341 for (i = 0; i < irk_count; i++) {
4342 struct mgmt_irk_info *irk = &cp->irks[i];
4343 u8 addr_type;
4344
4345 if (irk->addr.type == BDADDR_LE_PUBLIC)
4346 addr_type = ADDR_LE_DEV_PUBLIC;
4347 else
4348 addr_type = ADDR_LE_DEV_RANDOM;
4349
4350 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4351 BDADDR_ANY);
4352 }
4353
4354 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4355
4356 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4357
4358 hci_dev_unlock(hdev);
4359
4360 return err;
4361}
4362
Johan Hedberg3f706b72013-01-20 14:27:16 +02004363static bool ltk_is_valid(struct mgmt_ltk_info *key)
4364{
4365 if (key->master != 0x00 && key->master != 0x01)
4366 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004367
4368 switch (key->addr.type) {
4369 case BDADDR_LE_PUBLIC:
4370 return true;
4371
4372 case BDADDR_LE_RANDOM:
4373 /* Two most significant bits shall be set */
4374 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4375 return false;
4376 return true;
4377 }
4378
4379 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004380}
4381
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004382static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004383 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004384{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004385 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4386 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004387 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004388
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004389 BT_DBG("request for %s", hdev->name);
4390
4391 if (!lmp_le_capable(hdev))
4392 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4393 MGMT_STATUS_NOT_SUPPORTED);
4394
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004395 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004396
4397 expected_len = sizeof(*cp) + key_count *
4398 sizeof(struct mgmt_ltk_info);
4399 if (expected_len != len) {
4400 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004401 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004402 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004403 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004404 }
4405
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004406 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004407
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004408 for (i = 0; i < key_count; i++) {
4409 struct mgmt_ltk_info *key = &cp->keys[i];
4410
Johan Hedberg3f706b72013-01-20 14:27:16 +02004411 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004412 return cmd_status(sk, hdev->id,
4413 MGMT_OP_LOAD_LONG_TERM_KEYS,
4414 MGMT_STATUS_INVALID_PARAMS);
4415 }
4416
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004417 hci_dev_lock(hdev);
4418
4419 hci_smp_ltks_clear(hdev);
4420
4421 for (i = 0; i < key_count; i++) {
4422 struct mgmt_ltk_info *key = &cp->keys[i];
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004423 u8 type, addr_type;
4424
4425 if (key->addr.type == BDADDR_LE_PUBLIC)
4426 addr_type = ADDR_LE_DEV_PUBLIC;
4427 else
4428 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004429
4430 if (key->master)
4431 type = HCI_SMP_LTK;
4432 else
4433 type = HCI_SMP_LTK_SLAVE;
4434
Johan Hedberg35d70272014-02-19 14:57:47 +02004435 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
4436 key->type, key->val, key->enc_size, key->ediv,
4437 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004438 }
4439
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004440 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4441 NULL, 0);
4442
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004443 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004444
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004445 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004446}
4447
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004448static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004449 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4450 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004451 bool var_len;
4452 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004453} mgmt_handlers[] = {
4454 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004455 { read_version, false, MGMT_READ_VERSION_SIZE },
4456 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4457 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4458 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4459 { set_powered, false, MGMT_SETTING_SIZE },
4460 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4461 { set_connectable, false, MGMT_SETTING_SIZE },
4462 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4463 { set_pairable, false, MGMT_SETTING_SIZE },
4464 { set_link_security, false, MGMT_SETTING_SIZE },
4465 { set_ssp, false, MGMT_SETTING_SIZE },
4466 { set_hs, false, MGMT_SETTING_SIZE },
4467 { set_le, false, MGMT_SETTING_SIZE },
4468 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4469 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4470 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4471 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4472 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4473 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4474 { disconnect, false, MGMT_DISCONNECT_SIZE },
4475 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4476 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4477 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4478 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4479 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4480 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4481 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4482 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4483 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4484 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4485 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4486 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004487 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004488 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4489 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4490 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4491 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4492 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4493 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004494 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004495 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004496 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004497 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004498 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004499 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004500 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004501 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004502 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004503};
4504
4505
Johan Hedberg03811012010-12-08 00:21:06 +02004506int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4507{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004508 void *buf;
4509 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004510 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004511 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004512 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004513 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004514 int err;
4515
4516 BT_DBG("got %zu bytes", msglen);
4517
4518 if (msglen < sizeof(*hdr))
4519 return -EINVAL;
4520
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004521 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004522 if (!buf)
4523 return -ENOMEM;
4524
4525 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4526 err = -EFAULT;
4527 goto done;
4528 }
4529
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004530 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004531 opcode = __le16_to_cpu(hdr->opcode);
4532 index = __le16_to_cpu(hdr->index);
4533 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004534
4535 if (len != msglen - sizeof(*hdr)) {
4536 err = -EINVAL;
4537 goto done;
4538 }
4539
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004540 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004541 hdev = hci_dev_get(index);
4542 if (!hdev) {
4543 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004544 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004545 goto done;
4546 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004547
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004548 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4549 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004550 err = cmd_status(sk, index, opcode,
4551 MGMT_STATUS_INVALID_INDEX);
4552 goto done;
4553 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004554 }
4555
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004556 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004557 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004558 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004559 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004560 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004561 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004562 }
4563
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004564 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004565 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004566 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004567 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004568 goto done;
4569 }
4570
Johan Hedbergbe22b542012-03-01 22:24:41 +02004571 handler = &mgmt_handlers[opcode];
4572
4573 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004574 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004575 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004576 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004577 goto done;
4578 }
4579
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004580 if (hdev)
4581 mgmt_init_hdev(sk, hdev);
4582
4583 cp = buf + sizeof(*hdr);
4584
Johan Hedbergbe22b542012-03-01 22:24:41 +02004585 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004586 if (err < 0)
4587 goto done;
4588
Johan Hedberg03811012010-12-08 00:21:06 +02004589 err = msglen;
4590
4591done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004592 if (hdev)
4593 hci_dev_put(hdev);
4594
Johan Hedberg03811012010-12-08 00:21:06 +02004595 kfree(buf);
4596 return err;
4597}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004598
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004599void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004600{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004601 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004602 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004603
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004604 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004605}
4606
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004607void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004608{
Johan Hedberg5f159032012-03-02 03:13:19 +02004609 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004610
Marcel Holtmann1514b892013-10-06 08:25:01 -07004611 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004612 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004613
Johan Hedberg744cf192011-11-08 20:40:14 +02004614 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004615
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004616 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004617}
4618
Johan Hedberg229ab392013-03-15 17:06:53 -05004619static void powered_complete(struct hci_dev *hdev, u8 status)
4620{
4621 struct cmd_lookup match = { NULL, hdev };
4622
4623 BT_DBG("status 0x%02x", status);
4624
4625 hci_dev_lock(hdev);
4626
4627 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4628
4629 new_settings(hdev, match.sk);
4630
4631 hci_dev_unlock(hdev);
4632
4633 if (match.sk)
4634 sock_put(match.sk);
4635}
4636
Johan Hedberg70da6242013-03-15 17:06:51 -05004637static int powered_update_hci(struct hci_dev *hdev)
4638{
Johan Hedberg890ea892013-03-15 17:06:52 -05004639 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004640 u8 link_sec;
4641
Johan Hedberg890ea892013-03-15 17:06:52 -05004642 hci_req_init(&req, hdev);
4643
Johan Hedberg70da6242013-03-15 17:06:51 -05004644 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4645 !lmp_host_ssp_capable(hdev)) {
4646 u8 ssp = 1;
4647
Johan Hedberg890ea892013-03-15 17:06:52 -05004648 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004649 }
4650
Johan Hedbergc73eee92013-04-19 18:35:21 +03004651 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4652 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05004653 struct hci_cp_write_le_host_supported cp;
4654
4655 cp.le = 1;
4656 cp.simul = lmp_le_br_capable(hdev);
4657
4658 /* Check first if we already have the right
4659 * host state (host features set)
4660 */
4661 if (cp.le != lmp_host_le_capable(hdev) ||
4662 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05004663 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
4664 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004665 }
4666
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004667 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004668 /* Make sure the controller has a good default for
4669 * advertising data. This also applies to the case
4670 * where BR/EDR was toggled during the AUTO_OFF phase.
4671 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004672 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004673 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004674 update_scan_rsp_data(&req);
4675 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004676
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004677 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
4678 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03004679 }
4680
Johan Hedberg70da6242013-03-15 17:06:51 -05004681 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4682 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05004683 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
4684 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05004685
4686 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03004687 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
4688 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004689 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05004690 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004691 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05004692 }
4693
Johan Hedberg229ab392013-03-15 17:06:53 -05004694 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05004695}
4696
Johan Hedberg744cf192011-11-08 20:40:14 +02004697int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02004698{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02004699 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05004700 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
4701 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004702 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004703
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004704 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
4705 return 0;
4706
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004707 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05004708 if (powered_update_hci(hdev) == 0)
4709 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02004710
Johan Hedberg229ab392013-03-15 17:06:53 -05004711 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
4712 &match);
4713 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004714 }
4715
Johan Hedberg229ab392013-03-15 17:06:53 -05004716 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4717 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
4718
4719 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
4720 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
4721 zero_cod, sizeof(zero_cod), NULL);
4722
4723new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004724 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004725
4726 if (match.sk)
4727 sock_put(match.sk);
4728
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004729 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004730}
Johan Hedberg73f22f62010-12-29 16:00:25 +02004731
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004732void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03004733{
4734 struct pending_cmd *cmd;
4735 u8 status;
4736
4737 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
4738 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004739 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03004740
4741 if (err == -ERFKILL)
4742 status = MGMT_STATUS_RFKILLED;
4743 else
4744 status = MGMT_STATUS_FAILED;
4745
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004746 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004747
4748 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004749}
4750
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004751void mgmt_discoverable_timeout(struct hci_dev *hdev)
4752{
4753 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004754
4755 hci_dev_lock(hdev);
4756
4757 /* When discoverable timeout triggers, then just make sure
4758 * the limited discoverable flag is cleared. Even in the case
4759 * of a timeout triggered from general discoverable, it is
4760 * safe to unconditionally clear the flag.
4761 */
4762 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004763 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004764
4765 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03004766 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4767 u8 scan = SCAN_PAGE;
4768 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
4769 sizeof(scan), &scan);
4770 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004771 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004772 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004773 hci_req_run(&req, NULL);
4774
4775 hdev->discov_timeout = 0;
4776
Johan Hedberg9a43e252013-10-20 19:00:07 +03004777 new_settings(hdev, NULL);
4778
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004779 hci_dev_unlock(hdev);
4780}
4781
Marcel Holtmann86a75642013-10-15 06:33:54 -07004782void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02004783{
Marcel Holtmann86a75642013-10-15 06:33:54 -07004784 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02004785
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004786 /* Nothing needed here if there's a pending command since that
4787 * commands request completion callback takes care of everything
4788 * necessary.
4789 */
4790 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07004791 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004792
Johan Hedbergbd107992014-02-24 14:52:19 +02004793 /* Powering off may clear the scan mode - don't let that interfere */
4794 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4795 return;
4796
Johan Hedberg9a43e252013-10-20 19:00:07 +03004797 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07004798 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004799 } else {
4800 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07004801 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004802 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004803
Johan Hedberg9a43e252013-10-20 19:00:07 +03004804 if (changed) {
4805 struct hci_request req;
4806
4807 /* In case this change in discoverable was triggered by
4808 * a disabling of connectable there could be a need to
4809 * update the advertising flags.
4810 */
4811 hci_req_init(&req, hdev);
4812 update_adv_data(&req);
4813 hci_req_run(&req, NULL);
4814
Marcel Holtmann86a75642013-10-15 06:33:54 -07004815 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004816 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004817}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004818
Marcel Holtmanna3309162013-10-15 06:33:55 -07004819void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004820{
Marcel Holtmanna3309162013-10-15 06:33:55 -07004821 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004822
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004823 /* Nothing needed here if there's a pending command since that
4824 * commands request completion callback takes care of everything
4825 * necessary.
4826 */
4827 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07004828 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004829
Johan Hedbergce3f24c2014-02-24 14:52:20 +02004830 /* Powering off may clear the scan mode - don't let that interfere */
4831 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4832 return;
4833
Marcel Holtmanna3309162013-10-15 06:33:55 -07004834 if (connectable)
4835 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
4836 else
4837 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004838
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004839 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07004840 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004841}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004842
Johan Hedberg778b2352014-02-24 14:52:17 +02004843void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
4844{
4845 if (advertising)
4846 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4847 else
4848 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4849}
4850
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07004851void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004852{
Johan Hedbergca69b792011-11-11 18:10:00 +02004853 u8 mgmt_err = mgmt_status(status);
4854
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004855 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02004856 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004857 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004858
4859 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02004860 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004861 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004862}
4863
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004864void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
4865 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004866{
Johan Hedberg86742e12011-11-07 23:13:38 +02004867 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004868
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004869 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004870
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004871 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02004872 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03004873 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004874 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03004875 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004876 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004877
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004878 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004879}
Johan Hedbergf7520542011-01-20 12:34:39 +02004880
Johan Hedbergba74b662014-02-19 14:57:45 +02004881void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004882{
4883 struct mgmt_ev_new_long_term_key ev;
4884
4885 memset(&ev, 0, sizeof(ev));
4886
Marcel Holtmann5192d302014-02-19 17:11:58 -08004887 /* Devices using resolvable or non-resolvable random addresses
4888 * without providing an indentity resolving key don't require
4889 * to store long term keys. Their addresses will change the
4890 * next time around.
4891 *
4892 * Only when a remote device provides an identity address
4893 * make sure the long term key is stored. If the remote
4894 * identity is known, the long term keys are internally
4895 * mapped to the identity address. So allow static random
4896 * and public addresses here.
4897 */
Johan Hedbergba74b662014-02-19 14:57:45 +02004898 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
4899 (key->bdaddr.b[5] & 0xc0) != 0xc0)
4900 ev.store_hint = 0x00;
4901 else
4902 ev.store_hint = 0x01;
4903
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004904 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03004905 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Marcel Holtmannd40f3ee2014-01-31 18:42:17 -08004906 ev.key.type = key->authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004907 ev.key.enc_size = key->enc_size;
4908 ev.key.ediv = key->ediv;
4909
4910 if (key->type == HCI_SMP_LTK)
4911 ev.key.master = 1;
4912
4913 memcpy(ev.key.rand, key->rand, sizeof(key->rand));
4914 memcpy(ev.key.val, key->val, sizeof(key->val));
4915
Marcel Holtmann083368f2013-10-15 14:26:29 -07004916 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004917}
4918
Johan Hedberg95fbac82014-02-19 15:18:31 +02004919void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
4920{
4921 struct mgmt_ev_new_irk ev;
4922
4923 memset(&ev, 0, sizeof(ev));
4924
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08004925 /* For identity resolving keys from devices that are already
4926 * using a public address or static random address, do not
4927 * ask for storing this key. The identity resolving key really
4928 * is only mandatory for devices using resovlable random
4929 * addresses.
4930 *
4931 * Storing all identity resolving keys has the downside that
4932 * they will be also loaded on next boot of they system. More
4933 * identity resolving keys, means more time during scanning is
4934 * needed to actually resolve these addresses.
4935 */
4936 if (bacmp(&irk->rpa, BDADDR_ANY))
4937 ev.store_hint = 0x01;
4938 else
4939 ev.store_hint = 0x00;
4940
Johan Hedberg95fbac82014-02-19 15:18:31 +02004941 bacpy(&ev.rpa, &irk->rpa);
4942 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
4943 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
4944 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
4945
4946 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
4947}
4948
Marcel Holtmann94933992013-10-15 10:26:39 -07004949static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
4950 u8 data_len)
4951{
4952 eir[eir_len++] = sizeof(type) + data_len;
4953 eir[eir_len++] = type;
4954 memcpy(&eir[eir_len], data, data_len);
4955 eir_len += data_len;
4956
4957 return eir_len;
4958}
4959
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07004960void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
4961 u8 addr_type, u32 flags, u8 *name, u8 name_len,
4962 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02004963{
Johan Hedbergb644ba32012-01-17 21:48:47 +02004964 char buf[512];
4965 struct mgmt_ev_device_connected *ev = (void *) buf;
4966 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02004967
Johan Hedbergb644ba32012-01-17 21:48:47 +02004968 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03004969 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02004970
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02004971 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02004972
Johan Hedbergb644ba32012-01-17 21:48:47 +02004973 if (name_len > 0)
4974 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004975 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02004976
4977 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08004978 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004979 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02004980
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02004981 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02004982
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07004983 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
4984 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02004985}
4986
Johan Hedberg8962ee72011-01-20 12:40:27 +02004987static void disconnect_rsp(struct pending_cmd *cmd, void *data)
4988{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01004989 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004990 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02004991 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004992
Johan Hedberg88c3df12012-02-09 14:27:38 +02004993 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4994 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02004995
Johan Hedbergaee9b212012-02-18 15:07:59 +02004996 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004997 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02004998
4999 *sk = cmd->sk;
5000 sock_hold(*sk);
5001
Johan Hedberga664b5b2011-02-19 12:06:02 -03005002 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005003}
5004
Johan Hedberg124f6e32012-02-09 13:50:12 +02005005static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005006{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005007 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005008 struct mgmt_cp_unpair_device *cp = cmd->param;
5009 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005010
5011 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005012 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5013 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005014
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005015 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5016
Johan Hedbergaee9b212012-02-18 15:07:59 +02005017 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005018
5019 mgmt_pending_remove(cmd);
5020}
5021
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005022void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005023 u8 link_type, u8 addr_type, u8 reason,
5024 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005025{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005026 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005027 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005028
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005029 if (!mgmt_connected)
5030 return;
5031
Andre Guedes57eb7762013-10-30 19:01:41 -03005032 if (link_type != ACL_LINK && link_type != LE_LINK)
5033 return;
5034
Johan Hedberg744cf192011-11-08 20:40:14 +02005035 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005036
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005037 bacpy(&ev.addr.bdaddr, bdaddr);
5038 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5039 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005040
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005041 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005042
5043 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005044 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005045
Johan Hedberg124f6e32012-02-09 13:50:12 +02005046 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005047 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005048}
5049
Marcel Holtmann78929242013-10-06 23:55:47 -07005050void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5051 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005052{
Andre Guedes3655bba2013-10-30 19:01:40 -03005053 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5054 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005055 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005056 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005057
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005058 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5059 hdev);
5060
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005061 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005062 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005063 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005064
Andre Guedes3655bba2013-10-30 19:01:40 -03005065 cp = cmd->param;
5066
5067 if (bacmp(bdaddr, &cp->addr.bdaddr))
5068 return;
5069
5070 if (cp->addr.type != bdaddr_type)
5071 return;
5072
Johan Hedberg88c3df12012-02-09 14:27:38 +02005073 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005074 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005075
Marcel Holtmann78929242013-10-06 23:55:47 -07005076 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5077 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005078
Johan Hedberga664b5b2011-02-19 12:06:02 -03005079 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005080}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005081
Marcel Holtmann445608d2013-10-06 23:55:48 -07005082void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5083 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005084{
5085 struct mgmt_ev_connect_failed ev;
5086
Johan Hedberg4c659c32011-11-07 23:13:39 +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 Hedbergca69b792011-11-11 18:10:00 +02005089 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005090
Marcel Holtmann445608d2013-10-06 23:55:48 -07005091 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005092}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005093
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005094void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005095{
5096 struct mgmt_ev_pin_code_request ev;
5097
Johan Hedbergd8457692012-02-17 14:24:57 +02005098 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005099 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005100 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005101
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005102 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005103}
5104
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005105void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5106 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005107{
5108 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005109 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005110
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005111 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005112 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005113 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005114
Johan Hedbergd8457692012-02-17 14:24:57 +02005115 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005116 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005117
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005118 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5119 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005120
Johan Hedberga664b5b2011-02-19 12:06:02 -03005121 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005122}
5123
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005124void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5125 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005126{
5127 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005128 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005129
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005130 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005131 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005132 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005133
Johan Hedbergd8457692012-02-17 14:24:57 +02005134 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005135 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005136
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005137 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5138 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005139
Johan Hedberga664b5b2011-02-19 12:06:02 -03005140 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005141}
Johan Hedberga5c29682011-02-19 12:05:57 -03005142
Johan Hedberg744cf192011-11-08 20:40:14 +02005143int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005144 u8 link_type, u8 addr_type, __le32 value,
5145 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005146{
5147 struct mgmt_ev_user_confirm_request ev;
5148
Johan Hedberg744cf192011-11-08 20:40:14 +02005149 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005150
Johan Hedberg272d90d2012-02-09 15:26:12 +02005151 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005152 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005153 ev.confirm_hint = confirm_hint;
Andrei Emeltchenko78e80982012-03-09 13:00:50 +02005154 ev.value = value;
Johan Hedberga5c29682011-02-19 12:05:57 -03005155
Johan Hedberg744cf192011-11-08 20:40:14 +02005156 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005157 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005158}
5159
Johan Hedberg272d90d2012-02-09 15:26:12 +02005160int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005161 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005162{
5163 struct mgmt_ev_user_passkey_request ev;
5164
5165 BT_DBG("%s", hdev->name);
5166
Johan Hedberg272d90d2012-02-09 15:26:12 +02005167 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005168 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005169
5170 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005171 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005172}
5173
Brian Gix0df4c182011-11-16 13:53:13 -08005174static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005175 u8 link_type, u8 addr_type, u8 status,
5176 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005177{
5178 struct pending_cmd *cmd;
5179 struct mgmt_rp_user_confirm_reply rp;
5180 int err;
5181
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005182 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005183 if (!cmd)
5184 return -ENOENT;
5185
Johan Hedberg272d90d2012-02-09 15:26:12 +02005186 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005187 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005188 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005189 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005190
Johan Hedberga664b5b2011-02-19 12:06:02 -03005191 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005192
5193 return err;
5194}
5195
Johan Hedberg744cf192011-11-08 20:40:14 +02005196int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005197 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005198{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005199 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005200 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005201}
5202
Johan Hedberg272d90d2012-02-09 15:26:12 +02005203int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005204 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005205{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005206 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005207 status,
5208 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005209}
Johan Hedberg2a611692011-02-19 12:06:00 -03005210
Brian Gix604086b2011-11-23 08:28:33 -08005211int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005212 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005213{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005214 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005215 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005216}
5217
Johan Hedberg272d90d2012-02-09 15:26:12 +02005218int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005219 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005220{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005221 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005222 status,
5223 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005224}
5225
Johan Hedberg92a25252012-09-06 18:39:26 +03005226int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5227 u8 link_type, u8 addr_type, u32 passkey,
5228 u8 entered)
5229{
5230 struct mgmt_ev_passkey_notify ev;
5231
5232 BT_DBG("%s", hdev->name);
5233
5234 bacpy(&ev.addr.bdaddr, bdaddr);
5235 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5236 ev.passkey = __cpu_to_le32(passkey);
5237 ev.entered = entered;
5238
5239 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5240}
5241
Marcel Holtmanne5460992013-10-15 14:26:23 -07005242void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5243 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005244{
5245 struct mgmt_ev_auth_failed ev;
5246
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005247 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005248 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005249 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005250
Marcel Holtmanne5460992013-10-15 14:26:23 -07005251 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005252}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005253
Marcel Holtmann464996a2013-10-15 14:26:24 -07005254void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005255{
5256 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005257 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005258
5259 if (status) {
5260 u8 mgmt_err = mgmt_status(status);
5261 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005262 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005263 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005264 }
5265
Marcel Holtmann464996a2013-10-15 14:26:24 -07005266 if (test_bit(HCI_AUTH, &hdev->flags))
5267 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5268 &hdev->dev_flags);
5269 else
5270 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5271 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005272
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005273 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005274 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005275
Johan Hedberg47990ea2012-02-22 11:58:37 +02005276 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005277 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005278
5279 if (match.sk)
5280 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005281}
5282
Johan Hedberg890ea892013-03-15 17:06:52 -05005283static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005284{
Johan Hedberg890ea892013-03-15 17:06:52 -05005285 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005286 struct hci_cp_write_eir cp;
5287
Johan Hedberg976eb202012-10-24 21:12:01 +03005288 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005289 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005290
Johan Hedbergc80da272012-02-22 15:38:48 +02005291 memset(hdev->eir, 0, sizeof(hdev->eir));
5292
Johan Hedbergcacaf522012-02-21 00:52:42 +02005293 memset(&cp, 0, sizeof(cp));
5294
Johan Hedberg890ea892013-03-15 17:06:52 -05005295 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005296}
5297
Marcel Holtmann3e248562013-10-15 14:26:25 -07005298void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005299{
5300 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005301 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005302 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005303
5304 if (status) {
5305 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005306
5307 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005308 &hdev->dev_flags)) {
5309 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005310 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005311 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005312
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005313 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5314 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005315 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005316 }
5317
5318 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005319 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005320 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005321 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5322 if (!changed)
5323 changed = test_and_clear_bit(HCI_HS_ENABLED,
5324 &hdev->dev_flags);
5325 else
5326 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005327 }
5328
5329 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5330
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005331 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005332 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005333
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005334 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005335 sock_put(match.sk);
5336
Johan Hedberg890ea892013-03-15 17:06:52 -05005337 hci_req_init(&req, hdev);
5338
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005339 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005340 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005341 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005342 clear_eir(&req);
5343
5344 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005345}
5346
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005347void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5348{
5349 struct cmd_lookup match = { NULL, hdev };
5350 bool changed = false;
5351
5352 if (status) {
5353 u8 mgmt_err = mgmt_status(status);
5354
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005355 if (enable) {
5356 if (test_and_clear_bit(HCI_SC_ENABLED,
5357 &hdev->dev_flags))
5358 new_settings(hdev, NULL);
5359 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5360 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005361
5362 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5363 cmd_status_rsp, &mgmt_err);
5364 return;
5365 }
5366
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005367 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005368 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005369 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005370 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005371 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5372 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005373
5374 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5375 settings_rsp, &match);
5376
5377 if (changed)
5378 new_settings(hdev, match.sk);
5379
5380 if (match.sk)
5381 sock_put(match.sk);
5382}
5383
Johan Hedberg92da6092013-03-15 17:06:55 -05005384static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005385{
5386 struct cmd_lookup *match = data;
5387
Johan Hedberg90e70452012-02-23 23:09:40 +02005388 if (match->sk == NULL) {
5389 match->sk = cmd->sk;
5390 sock_hold(match->sk);
5391 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005392}
5393
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005394void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5395 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005396{
Johan Hedberg90e70452012-02-23 23:09:40 +02005397 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005398
Johan Hedberg92da6092013-03-15 17:06:55 -05005399 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5400 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5401 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005402
5403 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005404 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5405 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005406
5407 if (match.sk)
5408 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005409}
5410
Marcel Holtmann7667da32013-10-15 14:26:27 -07005411void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005412{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005413 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005414 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005415
Johan Hedberg13928972013-03-15 17:07:00 -05005416 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005417 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005418
5419 memset(&ev, 0, sizeof(ev));
5420 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005421 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005422
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005423 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005424 if (!cmd) {
5425 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005426
Johan Hedberg13928972013-03-15 17:07:00 -05005427 /* If this is a HCI command related to powering on the
5428 * HCI dev don't send any mgmt signals.
5429 */
5430 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005431 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005432 }
5433
Marcel Holtmann7667da32013-10-15 14:26:27 -07005434 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5435 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005436}
Szymon Jancc35938b2011-03-22 13:12:21 +01005437
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005438void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5439 u8 *randomizer192, u8 *hash256,
5440 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005441{
5442 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005443
Johan Hedberg744cf192011-11-08 20:40:14 +02005444 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005445
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005446 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005447 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005448 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005449
5450 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005451 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5452 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005453 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005454 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5455 hash256 && randomizer256) {
5456 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005457
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005458 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5459 memcpy(rp.randomizer192, randomizer192,
5460 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005461
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005462 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5463 memcpy(rp.randomizer256, randomizer256,
5464 sizeof(rp.randomizer256));
5465
5466 cmd_complete(cmd->sk, hdev->id,
5467 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5468 &rp, sizeof(rp));
5469 } else {
5470 struct mgmt_rp_read_local_oob_data rp;
5471
5472 memcpy(rp.hash, hash192, sizeof(rp.hash));
5473 memcpy(rp.randomizer, randomizer192,
5474 sizeof(rp.randomizer));
5475
5476 cmd_complete(cmd->sk, hdev->id,
5477 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5478 &rp, sizeof(rp));
5479 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005480 }
5481
5482 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005483}
Johan Hedberge17acd42011-03-30 23:57:16 +03005484
Marcel Holtmann901801b2013-10-06 23:55:51 -07005485void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5486 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
5487 ssp, u8 *eir, u16 eir_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005488{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005489 char buf[512];
5490 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005491 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005492 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005493
Andre Guedes12602d02013-04-30 15:29:40 -03005494 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005495 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005496
Johan Hedberg1dc06092012-01-15 21:01:23 +02005497 /* Leave 5 bytes for a potential CoD field */
5498 if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005499 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005500
Johan Hedberg1dc06092012-01-15 21:01:23 +02005501 memset(buf, 0, sizeof(buf));
5502
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005503 irk = hci_get_irk(hdev, bdaddr, addr_type);
5504 if (irk) {
5505 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5506 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5507 } else {
5508 bacpy(&ev->addr.bdaddr, bdaddr);
5509 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5510 }
5511
Johan Hedberge319d2e2012-01-15 19:51:59 +02005512 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005513 if (cfm_name)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305514 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005515 if (!ssp)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305516 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005517
Johan Hedberg1dc06092012-01-15 21:01:23 +02005518 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005519 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005520
Johan Hedberg1dc06092012-01-15 21:01:23 +02005521 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5522 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005523 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005524
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005525 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005526 ev_size = sizeof(*ev) + eir_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005527
Marcel Holtmann901801b2013-10-06 23:55:51 -07005528 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005529}
Johan Hedberga88a9652011-03-30 13:18:12 +03005530
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005531void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5532 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005533{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005534 struct mgmt_ev_device_found *ev;
5535 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5536 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005537
Johan Hedbergb644ba32012-01-17 21:48:47 +02005538 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005539
Johan Hedbergb644ba32012-01-17 21:48:47 +02005540 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005541
Johan Hedbergb644ba32012-01-17 21:48:47 +02005542 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005543 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005544 ev->rssi = rssi;
5545
5546 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005547 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005548
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005549 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005550
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005551 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005552}
Johan Hedberg314b2382011-04-27 10:29:57 -04005553
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005554void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005555{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005556 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005557 struct pending_cmd *cmd;
5558
Andre Guedes343fb142011-11-22 17:14:19 -03005559 BT_DBG("%s discovering %u", hdev->name, discovering);
5560
Johan Hedberg164a6e72011-11-01 17:06:44 +02005561 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005562 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005563 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005564 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005565
5566 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005567 u8 type = hdev->discovery.type;
5568
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005569 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5570 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005571 mgmt_pending_remove(cmd);
5572 }
5573
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005574 memset(&ev, 0, sizeof(ev));
5575 ev.type = hdev->discovery.type;
5576 ev.discovering = discovering;
5577
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005578 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04005579}
Antti Julku5e762442011-08-25 16:48:02 +03005580
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005581int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005582{
5583 struct pending_cmd *cmd;
5584 struct mgmt_ev_device_blocked ev;
5585
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005586 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005587
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005588 bacpy(&ev.addr.bdaddr, bdaddr);
5589 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005590
Johan Hedberg744cf192011-11-08 20:40:14 +02005591 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005592 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005593}
5594
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005595int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005596{
5597 struct pending_cmd *cmd;
5598 struct mgmt_ev_device_unblocked ev;
5599
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005600 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005601
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005602 bacpy(&ev.addr.bdaddr, bdaddr);
5603 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005604
Johan Hedberg744cf192011-11-08 20:40:14 +02005605 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005606 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005607}
Marcel Holtmann5976e602013-10-06 04:08:14 -07005608
5609static void adv_enable_complete(struct hci_dev *hdev, u8 status)
5610{
5611 BT_DBG("%s status %u", hdev->name, status);
5612
5613 /* Clear the advertising mgmt setting if we failed to re-enable it */
5614 if (status) {
5615 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005616 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005617 }
5618}
5619
5620void mgmt_reenable_advertising(struct hci_dev *hdev)
5621{
5622 struct hci_request req;
5623
Marcel Holtmannb145edc2013-10-10 09:47:54 -07005624 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07005625 return;
5626
5627 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5628 return;
5629
5630 hci_req_init(&req, hdev);
5631 enable_advertising(&req);
5632
5633 /* If this fails we have no option but to let user space know
5634 * that we've disabled advertising.
5635 */
5636 if (hci_req_run(&req, adv_enable_complete) < 0) {
5637 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005638 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005639 }
5640}